Skip to content

Commit

Permalink
Merge branch 'main' into feature/DP-396-outbox-wiring
Browse files Browse the repository at this point in the history
  • Loading branch information
jakzal committed Sep 24, 2024
2 parents 15fef38 + ccdfc85 commit a67dd47
Show file tree
Hide file tree
Showing 115 changed files with 8,023 additions and 295 deletions.
25 changes: 21 additions & 4 deletions Frontend/CO.CDP.OrganisationApp.Tests/AuthorizationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public HttpClient BuildHttpClient(List<string> userScopes)
"Org name",
[
Tenant.WebApiClient.PartyRole.Supplier,
Tenant.WebApiClient.PartyRole.ProcuringEntity
Tenant.WebApiClient.PartyRole.Tenderer
],
userScopes,
new Uri("http://foo")
Expand Down Expand Up @@ -78,7 +78,7 @@ [ organisation ]
testOrganisationId,
new Identifier("asd", "asd", "asd", new Uri("http://whatever")),
"Org name",
[ CO.CDP.Organisation.WebApiClient.PartyRole.Supplier, CO.CDP.Organisation.WebApiClient.PartyRole.ProcuringEntity ]
[ CO.CDP.Organisation.WebApiClient.PartyRole.Supplier, CO.CDP.Organisation.WebApiClient.PartyRole.Tenderer ]
)
);

Expand Down Expand Up @@ -169,7 +169,7 @@ public async Task TestAuthorizationIsUnsuccessful_WhenUserIsNotAllowedToAccessRe
[Fact]
public async Task TestCanSeeUsersLinkOnOrganisationPage_WhenUserIsAllowedToAccessResourceAsAdminUser()
{
var _httpClient = BuildHttpClient([ OrganisationPersonScopes.Admin ]);
var _httpClient = BuildHttpClient([ OrganisationPersonScopes.Admin, OrganisationPersonScopes.Viewer ]);

var request = new HttpRequestMessage(HttpMethod.Get, $"/organisation/{testOrganisationId}");

Expand All @@ -186,7 +186,7 @@ public async Task TestCanSeeUsersLinkOnOrganisationPage_WhenUserIsAllowedToAcces
[Fact]
public async Task TestCannotSeeUsersLinkOnOrganisationPage_WhenUserIsNotAllowedToAccessResourceAsEditorUser()
{
var _httpClient = BuildHttpClient([]);
var _httpClient = BuildHttpClient([ OrganisationPersonScopes.Editor ]);

var request = new HttpRequestMessage(HttpMethod.Get, $"/organisation/{testOrganisationId}");

Expand All @@ -201,4 +201,21 @@ public async Task TestCannotSeeUsersLinkOnOrganisationPage_WhenUserIsNotAllowedT
responseBody.Should().NotContain($"href=\"/organisation/{testOrganisationId}/users/user-summary\">Users</a>");
responseBody.Should().NotContain("Users");
}

[Fact]
public async Task TestCanSeeLinkToSupplierInformation_WhenUserIsAdmin()
{
var _httpClient = BuildHttpClient([OrganisationPersonScopes.Admin]);

var request = new HttpRequestMessage(HttpMethod.Get, $"/organisation/{testOrganisationId}");

var response = await _httpClient.SendAsync(request);

var responseBody = await response.Content.ReadAsStringAsync();

responseBody.Should().NotBeNull();
response.StatusCode.Should().Be(HttpStatusCode.OK);

responseBody.Should().Contain("Supplier information");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using Amazon.S3;
using CO.CDP.Organisation.WebApiClient;
using CO.CDP.OrganisationApp.Constants;
using CO.CDP.OrganisationApp.Pages.ApiKeyManagement;
using FluentAssertions;
using FluentAssertions.Equivalency;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Moq;
using System.Net;
using ProblemDetails = CO.CDP.Organisation.WebApiClient.ProblemDetails;

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

public class CreateApiKeyTest
{
private readonly Mock<IOrganisationClient> _mockOrganisationClient = new();
private readonly Guid _organisationId = Guid.NewGuid();
private readonly CreateApiKeyModel _model;
public CreateApiKeyTest()
{
_model = new CreateApiKeyModel(_mockOrganisationClient.Object);
}

[Fact]
public async Task OnPost_WhenModelStateIsInvalid_ShouldReturnPage()
{
_model.ModelState.AddModelError("key", "error");

var result = await _model.OnPost();

result.Should().BeOfType<PageResult>();
}

[Fact]
public async Task OnPost_WhenApiExceptionOccurs_ShouldRedirectToPageNotFound()
{
_mockOrganisationClient.Setup(client => client.CreateAuthenticationKeyAsync(It.IsAny<Guid>(), It.IsAny<RegisterAuthenticationKey>()))
.ThrowsAsync(new ApiException(string.Empty, (int)HttpStatusCode.NotFound, string.Empty, null, null));

_model.Id = Guid.NewGuid();
_model.ApiKeyName = "TestApiKey";

var result = await _model.OnPost();

result.Should().BeOfType<RedirectResult>()
.Which.Url.Should().Be("/page-not-found");
}

[Fact]
public async Task OnPost_ShouldRedirectToManageApiKey()
{
_model.Id = Guid.NewGuid();

_mockOrganisationClient
.Setup(c => c.CreateAuthenticationKeyAsync(_organisationId, DummyApiKeyEntity()));

var result = await _model.OnPost();

var redirectToPageResult = result.Should().BeOfType<RedirectToPageResult>().Subject;

_mockOrganisationClient.Verify(c => c.CreateAuthenticationKeyAsync(It.IsAny<Guid>(), It.IsAny<RegisterAuthenticationKey>()), Times.Once());

redirectToPageResult.PageName.Should().Be("NewApiKeyDetails");
}

[Fact]
public async Task OnPost_ShouldReturnPage_WhenCreateApiKeyModelStateIsInvalid()
{
var model = new CreateApiKeyModel(_mockOrganisationClient.Object);

model.ModelState.AddModelError("ApiKeyName", "Enter the api key name");

var result = await model.OnPost();

result.Should().BeOfType<PageResult>();
}

[Theory]
[InlineData(ErrorCodes.APIKEY_NAME_ALREADY_EXISTS, ErrorMessagesList.DuplicateApiKeyName, StatusCodes.Status400BadRequest)]
public async Task OnPost_AddsModelError(string errorCode, string expectedErrorMessage, int statusCode)
{
var problemDetails = new ProblemDetails(
title: errorCode,
detail: ErrorMessagesList.DuplicateApiKeyName,
status: statusCode,
instance: null,
type: null
)
{
AdditionalProperties =
{
{ "code", "APIKEY_NAME_ALREADY_EXISTS" }
}
};
var aex = new ApiException<ProblemDetails>(
"Duplicate Api key name",
statusCode,
"Bad Request",
null,
problemDetails ?? new ProblemDetails("Detail", "Instance", statusCode, "Problem title", "Problem type"),
null
);

_mockOrganisationClient.Setup(client => client.CreateAuthenticationKeyAsync(It.IsAny<Guid>(), It.IsAny<RegisterAuthenticationKey>()))
.ThrowsAsync(aex);

_model.Id = Guid.NewGuid();
_model.ApiKeyName = "TestApiKey";

var result = await _model.OnPost();

_model.ModelState[string.Empty].As<ModelStateEntry>().Errors
.Should().Contain(e => e.ErrorMessage == expectedErrorMessage);
}

private RegisterAuthenticationKey DummyApiKeyEntity()
{
return new RegisterAuthenticationKey(key: "_key", name: "name", organisationId: _organisationId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using CO.CDP.Organisation.WebApiClient;
using CO.CDP.OrganisationApp.Pages.ApiKeyManagement;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Moq;
using System.Net;

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

public class ManageApiKeyTest
{
private readonly Mock<IOrganisationClient> _mockOrganisationClient = new();
private readonly ManageApiKeyModel _model;

public ManageApiKeyTest()
{
_model = new ManageApiKeyModel(_mockOrganisationClient.Object);
_model.Id = Guid.NewGuid();
}

[Fact]
public async Task OnGet_WhenAuthenticationKeysAreRetrieved_ShouldReturnPage()
{
var authenticationKeys = new List<AuthenticationKey> {
new AuthenticationKey(createdOn: DateTimeOffset.UtcNow.AddDays(-1), name: "TestKey1", revoked: false, revokedOn: DateTimeOffset.UtcNow)
};

_mockOrganisationClient
.Setup(client => client.GetAuthenticationKeysAsync(It.IsAny<Guid>()))
.ReturnsAsync(authenticationKeys);

var result = await _model.OnGet();

result.Should().BeOfType<PageResult>();

_model.AuthenticationKeys.Should().HaveCount(1);
_model.AuthenticationKeys.FirstOrDefault()!.Name.Should().Be("TestKey1");
}

[Fact]
public async Task OnGet_WhenApiExceptionOccurs_ShouldRedirectToPageNotFound()
{
_mockOrganisationClient.Setup(client => client.GetAuthenticationKeysAsync(It.IsAny<Guid>()))
.ThrowsAsync(new ApiException(string.Empty, (int)HttpStatusCode.NotFound, string.Empty, null, null));

var result = await _model.OnGet();

result.Should().BeOfType<RedirectResult>()
.Which.Url.Should().Be("/page-not-found");
}

[Fact]
public void OnPost_ShouldRedirectToCreateApiKeyPage()
{
var result = _model.OnPost();

result.Should().BeOfType<RedirectToPageResult>()
.Which.PageName.Should().Be("CreateApiKey");

result.As<RedirectToPageResult>().RouteValues!["Id"].Should().Be(_model.Id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using CO.CDP.OrganisationApp.Pages.ApiKeyManagement;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.RazorPages;

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

public class NewApiKeyDetailsTest
{
[Fact]
public void OnGet_ShouldReturnPageResult()
{
var pageModel = new NewApiKeyDetailsModel
{
Id = Guid.NewGuid(),
ApiKey = "test-api-key"
};

var result = pageModel.OnGet();

result.Should().BeOfType<PageResult>();
pageModel.Id.Should().NotBeEmpty();
pageModel.ApiKey.Should().Be("test-api-key");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using CO.CDP.Organisation.WebApiClient;
using CO.CDP.OrganisationApp.Pages.ApiKeyManagement;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Moq;
using System.Net;

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

public class RevokeApiKeyTest
{
private readonly Mock<IOrganisationClient> _mockOrganisationClient;
private readonly RevokeApiKeyModel _pageModel;

public RevokeApiKeyTest()
{
_mockOrganisationClient = new Mock<IOrganisationClient>();
_pageModel = new RevokeApiKeyModel(_mockOrganisationClient.Object)
{
Id = Guid.NewGuid(),
ApiKeyName = "TestApiKey"
};
}

[Fact]
public async Task OnPost_ValidModelState_ShouldRedirectToManageApiKeyPage()
{
_mockOrganisationClient
.Setup(client => client.RevokeAuthenticationKeyAsync(It.IsAny<Guid>(), It.IsAny<string>()))
.Returns(Task.CompletedTask);

var result = await _pageModel.OnPost();

result.Should().BeOfType<RedirectToPageResult>()
.Which.PageName.Should().Be("ManageApiKey");
result.As<RedirectToPageResult>().RouteValues!["Id"].Should().Be(_pageModel.Id);

_mockOrganisationClient.Verify(client => client.RevokeAuthenticationKeyAsync(_pageModel.Id, _pageModel.ApiKeyName), Times.Once);
}

[Fact]
public async Task OnPost_InvalidModelState_ShouldReturnPageResult()
{
_pageModel.ModelState.AddModelError("ApiKeyName", "ApiKeyName is required");

var result = await _pageModel.OnPost();

result.Should().BeOfType<PageResult>();

_mockOrganisationClient.Verify(client => client.RevokeAuthenticationKeyAsync(It.IsAny<Guid>(), It.IsAny<string>()), Times.Never);
}

[Fact]
public async Task OnPost_ApiException404_ShouldRedirectToPageNotFound()
{
_mockOrganisationClient.Setup(client => client.RevokeAuthenticationKeyAsync(It.IsAny<Guid>(), It.IsAny<string>()))
.ThrowsAsync(new ApiException(string.Empty, (int)HttpStatusCode.NotFound, string.Empty, null, null));

var result = await _pageModel.OnPost();

result.Should().BeOfType<RedirectResult>()
.Which.Url.Should().Be("/page-not-found");

_mockOrganisationClient.Verify(client => client.RevokeAuthenticationKeyAsync(_pageModel.Id, _pageModel.ApiKeyName), Times.Once);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void OnPost_ShouldRedirectToCorrectPage_WhenYesOptionIsSelected()
It.IsAny<Guid>(),
It.IsAny<FormQuestionAnswerState>()
), Times.Never);
redirectResult!.PageName.Should().Be("");
redirectResult!.PageName.Should().Be("../Forms/DynamicFormsPage");
redirectResult.RouteValues.Should().ContainKey("OrganisationId").WhoseValue.Should().Be(organisationId);
redirectResult.RouteValues.Should().ContainKey("FormId").WhoseValue.Should().Be(formId);
redirectResult.RouteValues.Should().ContainKey("SectionId").WhoseValue.Should().Be(sectionId);
Expand Down
Loading

0 comments on commit a67dd47

Please sign in to comment.