Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/dp 821 buyer approval tabs pagination #1164

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5a47b5d
Adding pagination
rmohammed-goaco Jan 14, 2025
586d405
Support Admin - Organisations tabs and pagination
rmohammed-goaco Jan 20, 2025
71175e6
Merge branch 'main' into feature/DP-821-buyer-approval-tabs-pagination
rmohammed-goaco Jan 20, 2025
3b41eb3
Added unit tests and applied PR feedback
rmohammed-goaco Jan 21, 2025
cdb53a8
PageUrl fix and additional tests
rmohammed-goaco Jan 21, 2025
760e142
Fix translations
rmohammed-goaco Jan 21, 2025
792a87f
Merge branch 'main' into feature/DP-821-buyer-approval-tabs-pagination
rmohammed-goaco Jan 21, 2025
22bd055
Feedback
rmohammed-goaco Jan 21, 2025
cf932f0
Merge branch 'feature/DP-821-buyer-approval-tabs-pagination' of githu…
rmohammed-goaco Jan 21, 2025
03e0428
Fix warnings
rmohammed-goaco Jan 21, 2025
2512c50
Fix tests
rmohammed-goaco Jan 21, 2025
1c3ec38
Merge branch 'main' into feature/DP-821-buyer-approval-tabs-pagination
rmohammed-goaco Jan 22, 2025
5f8a18e
Change from string to PartyRole and "tenderer" instead of "supplier"
rmohammed-goaco Jan 22, 2025
d654ff2
Merge branch 'feature/DP-821-buyer-approval-tabs-pagination' of githu…
rmohammed-goaco Jan 22, 2025
94a8ce9
Refactoring support admin organisation endpoints to deal with pure Pa…
andymantell Jan 22, 2025
5ef4003
Update unit tests
rmohammed-goaco Jan 22, 2025
c1e1ae4
Merge branch 'main' into feature/DP-821-buyer-approval-tabs-pagination
rmohammed-goaco Jan 22, 2025
7ccfe1d
Fix more tests
rmohammed-goaco Jan 22, 2025
1e6abb3
Merge branch 'feature/DP-821-buyer-approval-tabs-pagination' of githu…
rmohammed-goaco Jan 22, 2025
0fda47e
Feedback addressed
rmohammed-goaco Jan 22, 2025
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
@@ -0,0 +1,74 @@
using CO.CDP.OrganisationApp.Pages.Shared;
using FluentAssertions;
using System.ComponentModel.DataAnnotations;

public class PaginationPartialModelTests
{
[Fact]
public void TotalPages_CalculatesCorrectly_WhenDivisible()
{
var model = new PaginationPartialModel
{
TotalItems = 100,
PageSize = 10,
CurrentPage = 1,
Url = "/test"
};

var totalPages = model.TotalPages;

totalPages.Should().Be(10);
}

[Fact]
public void TotalPages_CalculatesCorrectly_WhenNotDivisible()
{
var model = new PaginationPartialModel
{
TotalItems = 101,
PageSize = 10,
CurrentPage = 1,
Url = "/test"
};

var totalPages = model.TotalPages;

totalPages.Should().Be(11);
}

[Fact]
public void GetPageUrl_ReturnsCorrectUrl()
{
var model = new PaginationPartialModel
{
TotalItems = 100,
PageSize = 10,
CurrentPage = 1,
Url = "/test"
};

var pageUrl = model.GetPageUrl(2);

pageUrl.Should().Be("/test?pageNumber=2&pageSize=10");
}

[Fact]
public void Model_WithAllRequiredProperties_ShouldPassValidation()
{
var model = new PaginationPartialModel
{
CurrentPage = 1,
TotalItems = 100,
PageSize = 10,
Url = "/test"
};

var validationResults = new List<ValidationResult>();
var validationContext = new ValidationContext(model);

var isValid = Validator.TryValidateObject(model, validationContext, validationResults, true);

isValid.Should().BeTrue();
validationResults.Should().BeEmpty();
}
}
198 changes: 78 additions & 120 deletions Frontend/CO.CDP.OrganisationApp.Tests/Pages/Support/OrganisationsTest.cs
Original file line number Diff line number Diff line change
@@ -1,155 +1,113 @@
using CO.CDP.Organisation.WebApiClient;
using CO.CDP.OrganisationApp.Pages.Support;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Moq;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace CO.CDP.OrganisationApp.Tests.Pages.Support;

public class OrganisationsModelTests
{
private readonly Mock<IOrganisationClient> _organisationClientMock;
private readonly Mock<ISession> _sessionMock;
private readonly Mock<IOrganisationClient> _mockOrganisationClient;
private readonly Mock<ISession> _mockSession;
private readonly OrganisationsModel _organisationsModel;

public OrganisationsModelTests()
{
_organisationClientMock = new Mock<IOrganisationClient>();
_sessionMock = new Mock<ISession>();
_organisationsModel = new OrganisationsModel(_organisationClientMock.Object, _sessionMock.Object);
_mockOrganisationClient = new Mock<IOrganisationClient>();
_mockSession = new Mock<ISession>();
_organisationsModel = new OrganisationsModel(_mockOrganisationClient.Object, _mockSession.Object);
}

[Fact]
public async Task OnGet_ValidType_SetsTitleAndOrganisations_ReturnsPageResult()
public async Task OnGet_SetsPropertiesCorrectly_ForBuyerType()
{
var type = "buyer";
var orgs = new List<OrganisationExtended>
{
new OrganisationExtended(
additionalIdentifiers: new List<Identifier>
{
new Identifier(
id: "12345678",
legalName: "Mock Legal Name 1",
scheme: "GB-COH",
uri: new Uri("http://example.com/1")
)
},
addresses: new List<Address>
{
new Address(
country: "GB",
countryName: "United Kingdom",
locality: "Mock Town",
postalCode: "MK1 1AB",
region: "Mockshire",
streetAddress: "123 Mock St",
type: AddressType.Postal
)
},
contactPoint: new ContactPoint(
name: "John Doe",
email: "[email protected]",
telephone: "+441234567890",
url: new Uri("http://example.com/contact")
),
details: null,
id: Guid.NewGuid(),
identifier: new Identifier(
id: "12345678",
legalName: "Mock Legal Name 1",
scheme: "GB-COH",
uri: new Uri("http://example.com/1")
),
name: "Mock Organisation 1",
type: OrganisationType.Organisation,
roles: new List<PartyRole> { PartyRole.Buyer, PartyRole.Supplier }
),
new OrganisationExtended(
additionalIdentifiers: new List<Identifier>
{
new Identifier(
id: "87654321",
legalName: "Mock Legal Name 2",
scheme: "GB-COH",
uri: new Uri("http://example.com/2")
)
},
addresses: new List<Address>
{
new Address(
country: "GB",
countryName: "United Kingdom",
locality: "Testville",
postalCode: "TS2 2XY",
region: "Testshire",
streetAddress: "456 Test Lane",
type: AddressType.Postal
)
},
contactPoint: new ContactPoint(
name: "Jane Doe",
email: "[email protected]",
telephone: "+441234567892",
url: new Uri("http://example.com/contact2")
),
details: null,
id: Guid.NewGuid(),
identifier: new Identifier(
id: "87654321",
legalName: "Mock Legal Name 2",
scheme: "GB-COH",
uri: new Uri("http://example.com/2")
),
name: "Mock Organisation 2",
type: OrganisationType.Organisation,
roles: new List<PartyRole> { PartyRole.Buyer }
)
};

_organisationClientMock.Setup(client => client.GetAllOrganisationsAsync(type, 1000, 0))
.ReturnsAsync(orgs);
string type = "buyer";
int pageNumber = 1;
int totalOrganisations = 25;
var organisations = new List<OrganisationExtended>();
_mockOrganisationClient.Setup(client => client.GetAllOrganisationsAsync(type, type, 10, 0)).ReturnsAsync(organisations);
_mockOrganisationClient.Setup(client => client.GetOrganisationsTotalCountAsync(type, type)).ReturnsAsync(totalOrganisations);

var result = await _organisationsModel.OnGet(type);
var result = await _organisationsModel.OnGet(type, pageNumber);

_organisationsModel.Type.Should().Be(type);
_organisationsModel.Title.Should().Be("Buyer organisations");
_organisationsModel.Organisations.Should().HaveCount(2);
result.Should().BeOfType<PageResult>();

_organisationClientMock.Verify(client => client.GetAllOrganisationsAsync(type, 1000, 0), Times.Once);
_organisationsModel.Title.Should().Be("Buyer organisations");
_organisationsModel.PageSize.Should().Be(10);
_organisationsModel.CurrentPage.Should().Be(pageNumber);
_organisationsModel.TotalPages.Should().Be(3);
}

[Fact]
public async Task OnGet_EmptyOrganisations_ReturnsPageResultWithEmptyList()
public async Task OnGet_SetsPropertiesCorrectly_ForSupplierType()
{
var type = "buyer";
var orgs = new List<OrganisationExtended>();
string type = "supplier";
string role = "tenderer";
int pageNumber = 2;
int totalOrganisations = 35;
var organisations = new List<OrganisationExtended>();
_mockOrganisationClient.Setup(client => client.GetAllOrganisationsAsync(role, null, 10, 10)).ReturnsAsync(organisations);
_mockOrganisationClient.Setup(client => client.GetOrganisationsTotalCountAsync(role, null)).ReturnsAsync(totalOrganisations);

_organisationClientMock.Setup(client => client.GetAllOrganisationsAsync(type, 1000, 0))
.ReturnsAsync(orgs);
var result = await _organisationsModel.OnGet(type, pageNumber);

var result = await _organisationsModel.OnGet(type);

_organisationsModel.Type.Should().Be(type);
_organisationsModel.Title.Should().Be("Buyer organisations");
_organisationsModel.Organisations.Should().BeEmpty();
result.Should().BeOfType<PageResult>();

_organisationClientMock.Verify(client => client.GetAllOrganisationsAsync(type, 1000, 0), Times.Once);
_organisationsModel.Title.Should().Be("Supplier organisations");
_organisationsModel.PageSize.Should().Be(10);
_organisationsModel.CurrentPage.Should().Be(pageNumber);
_organisationsModel.TotalPages.Should().Be(4);
}

[Fact]
public async Task OnGet_ClientThrowsException_PropagatesException()
public void CombineIdentifiers_ReturnsCorrectList()
{
var type = "supplier";
_organisationClientMock.Setup(client => client.GetAllOrganisationsAsync(type, 1000, 0))
.ThrowsAsync(new Exception("API error"));
var identifier = new Identifier(
id: "12345678",
legalName: "Mock Legal Name 1",
scheme: "GB-COH",
uri: new Uri("http://example.com/1")
);

var additionalIdentifiers = new List<Identifier>
{
new Identifier(
id: "12345678",
legalName: "Mock Legal Name 1",
scheme: "GB-COH",
uri: new Uri("http://example.com/1")
),
new Identifier(
id: "12345678",
legalName: "Mock Legal Name 1",
scheme: "GB-COH",
uri: new Uri("http://example.com/1")
)
};

var result = OrganisationsModel.CombineIdentifiers(identifier, additionalIdentifiers);

result.Should().HaveCount(3);
result.Should().Contain(identifier);
result.Should().Contain(additionalIdentifiers[0]);
result.Should().Contain(additionalIdentifiers[1]);
}

Func<Task> act = async () => await _organisationsModel.OnGet(type);
[Fact]
public void CombineIdentifiers_HandlesNullIdentifier()
{
var additionalIdentifiers = new List<Identifier>
{
new Identifier(
id: "12345678",
legalName: "Mock Legal Name 1",
scheme: "GB-COH",
uri: new Uri("http://example.com/1")
)
};

await act.Should().ThrowAsync<Exception>().WithMessage("API error");
var result = OrganisationsModel.CombineIdentifiers(null, additionalIdentifiers);

_organisationClientMock.Verify(client => client.GetAllOrganisationsAsync(type, 1000, 0), Times.Once);
result.Should().HaveCount(1);
result[0].Id.Should().Be("12345678");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;

namespace CO.CDP.OrganisationApp.Pages.Shared
{
public class PaginationPartialModel
{
[Required]
public required int CurrentPage { get; set; }

[Required]
public required int TotalItems { get; set; }

[Required]
public required int PageSize { get; set; }

[Required]
public required string Url { get; set; }

public int TotalPages => (int)Math.Ceiling((double)TotalItems / PageSize);

public Func<int, string> GetPageUrl => (page) =>
$"{Url}?pageNumber={page}&pageSize={PageSize}";
}
}
Loading
Loading