Skip to content

Commit

Permalink
Merge pull request #410 from UKHO/dev/194581-integrate-ess-s100-updat…
Browse files Browse the repository at this point in the history
…esince-to-scs-stub

194581 - integrate s100 ess updatesince endpoint to scs stub
  • Loading branch information
jrippington authored Jan 15, 2025
2 parents d4047c5 + 5ef7313 commit 5210ca7
Show file tree
Hide file tree
Showing 23 changed files with 451 additions and 203 deletions.
12 changes: 11 additions & 1 deletion OpenApiSpecs/exchangeSetService_OpenApi_definition_internal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ paths:

"403":
$ref: "#/components/responses/forbidden"

'404':
$ref: '#/components/responses/NotFoundResponse'

"429":
$ref: "#/components/responses/tooManyRequests"
Expand Down Expand Up @@ -554,7 +557,14 @@ components:
schema:
type: integer
description: Specifies the time you should wait in seconds before retrying.


NotFoundResponse:
description: Not found.
content:
application/json:
schema:
$ref: '#/components/schemas/DefaultErrorResponse'

internalServerError:
description: Internal Server Error.
content:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,12 @@ namespace UKHO.ExchangeSetService.API.FunctionalTests.FunctionalTests.S_100
{
public class S100EssEndPointsScenarios : ObjectStorage
{
private string sinceDateTime;
private UpdatesSinceModel sinceDateTimePayload;
private List<string> productNames;

[OneTimeSetUp]
public void OneTimeSetUp()
{
sinceDateTime = DateTime.UtcNow.AddDays(-12).ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
sinceDateTimePayload = DataHelper.GetSinceDateTime(sinceDateTime);
ProductVersionData =
[
DataHelper.GetProductVersionModelData("102NO32904820801012",7, 1),
Expand All @@ -27,21 +24,83 @@ public void OneTimeSetUp()
productNames = DataHelper.GetProductNamesForS100();
}

[SetUp]
public void SetUp()
{
sinceDateTimePayload = DataHelper.GetSinceDateTime(DateTime.UtcNow.AddDays(-1).ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture)); // Default value of -1
}

//PBI 194403: Azure AD Authorization
//PBI 194581: Integrate S-100 ESS API Endpoint /updatesSince with corresponding SCS Stub
[Test]
[Category("QCOnlyTest-AIOEnabled")]
public async Task WhenICallS100UpdatesSinceEndPointWithValidTokenAndValidDate_ThenResponseCodeReturnedIs202Accepted()
{
var apiResponse = await ExchangeSetApiClient.GetExchangeSetBasedOnDateTimeAsync(null, null, EssJwtToken, "s100", sinceDateTimePayload);
Assert.That((int)apiResponse.StatusCode, Is.EqualTo(202), $"Incorrect status code is returned {apiResponse.StatusCode}, instead of the expected 202.");
await apiResponse.VerifyEssS100ApiResponseBodyDetails(0, 7, 0);
}

//PBI 194403: Azure AD Authorization
//PBI 194581: Integrate S-100 ESS API Endpoint /updatesSince with corresponding SCS Stub
[Test]
[Category("QCOnlyTest-AIOEnabled")]
public async Task WhenICallS100UpdatesSinceEndPointWithValidToken_ThenResponseCodeReturnedIs202Accepted()
public async Task WhenICallS100UpdatesSinceEndPointWithValidTokenAndValidDateWithProductIdentifierParam_ThenResponseCodeReturnedIs202Accepted()
{
var apiResponse = await ExchangeSetApiClient.GetExchangeSetBasedOnDateTimeAsync(sinceDateTime, null, EssJwtToken, "s100", sinceDateTimePayload);
var apiResponse = await ExchangeSetApiClient.GetExchangeSetBasedOnDateTimeAsync(null, null, EssJwtToken, "s100", sinceDateTimePayload, "s102");
Assert.That((int)apiResponse.StatusCode, Is.EqualTo(202), $"Incorrect status code is returned {apiResponse.StatusCode}, instead of the expected 202.");
await apiResponse.VerifyEssS100ApiResponseBodyDetails(0, 8, 0);
}

//PBI 194403: Azure AD Authorization
//PBI 194581: Integrate S-100 ESS API Endpoint /updatesSince with corresponding SCS Stub
[Test]
[Category("QCOnlyTest-AIOEnabled")]
public async Task WhenICallS100UpdatesSinceEndPointWithValidTokenForADateWhichHasNoUpdateWithProductIdentifierParam_ThenResponseCodeReturnedIs304NotModified()
{
sinceDateTimePayload = DataHelper.GetSinceDateTime(DateTime.UtcNow.AddDays(-10).ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture)); // Set a date that has no updates
var apiResponse = await ExchangeSetApiClient.GetExchangeSetBasedOnDateTimeAsync(null, null, EssJwtToken, "s100", sinceDateTimePayload, "s111");
Assert.That((int)apiResponse.StatusCode, Is.EqualTo(304), $"Incorrect status code is returned {apiResponse.StatusCode}, instead of the expected 304.");
Assert.That(await apiResponse.Content.ReadAsStringAsync(), Is.Empty, "Response body is not empty.");
}

//PBI 194403: Azure AD Authorization
//PBI 194581: Integrate S-100 ESS API Endpoint /updatesSince with corresponding SCS Stub
[Test]
[Category("QCOnlyTest-AIOEnabled")]
public async Task WhenICallS100UpdatesSinceEndPointWithValidTokenButWithInValidDateTimeFormat_ThenResponseCodeReturnedIs400BadRequest()
{
sinceDateTimePayload = DataHelper.GetSinceDateTime(DateTime.UtcNow.AddDays(-10).ToString("MM/dd/yyyy HH:mm", CultureInfo.InvariantCulture));
var apiResponse = await ExchangeSetApiClient.GetExchangeSetBasedOnDateTimeAsync(null, null, EssJwtToken, "s100", sinceDateTimePayload);
Assert.That((int)apiResponse.StatusCode, Is.EqualTo(400), $"Incorrect status code is returned {apiResponse.StatusCode}, instead of the expected 400.");
}

//PBI 194403: Azure AD Authorization
//PBI 194581: Integrate S-100 ESS API Endpoint /updatesSince with corresponding SCS Stub
[Test]
[Category("QCOnlyTest-AIOEnabled")]
public async Task WhenICallS100UpdatesSinceEndPointWithValidTokenButWithInValidProductIdentifierParam_ThenResponseCodeReturnedIs400BadRequest()
{
var apiResponse = await ExchangeSetApiClient.GetExchangeSetBasedOnDateTimeAsync(null, null, EssJwtToken, "s100", sinceDateTimePayload, "a101");
Assert.That((int)apiResponse.StatusCode, Is.EqualTo(400), $"Incorrect status code is returned {apiResponse.StatusCode}, instead of the expected 400.");
}

//PBI 194403: Azure AD Authorization
//PBI 194581: Integrate S-100 ESS API Endpoint /updatesSince with corresponding SCS Stub
[Test]
[Category("QCOnlyTest-AIOEnabled")]
public async Task WhenICallS100UpdatesSinceEndPointWithValidTokenAndValidButNonExistingProductIdentifierParam_ThenResponseCodeReturnedIs404NotFound()
{
var apiResponse = await ExchangeSetApiClient.GetExchangeSetBasedOnDateTimeAsync(null, null, EssJwtToken, "s100", sinceDateTimePayload, "s999");
Assert.That((int)apiResponse.StatusCode, Is.EqualTo(404), $"Incorrect status code is returned {apiResponse.StatusCode}, instead of the expected 404.");
}

//PBI 194403: Azure AD Authorization
[Test]
[Category("QCOnlyTest-AIOEnabled")]
public async Task WhenICallS100UpdatesSinceEndPointWithInvalidToken_ThenResponseCodeReturnedIs401Unauthorized()
{
var apiResponse = await ExchangeSetApiClient.GetExchangeSetBasedOnDateTimeAsync(sinceDateTime, null, "InvalidEssJwtToken", "s100", sinceDateTimePayload);
var apiResponse = await ExchangeSetApiClient.GetExchangeSetBasedOnDateTimeAsync(null, null, "InvalidEssJwtToken", "s100", sinceDateTimePayload);
Assert.That((int)apiResponse.StatusCode, Is.EqualTo(401), $"Incorrect status code is returned {apiResponse.StatusCode}, instead of the expected 401.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,21 @@ public ExchangeSetApiClient(string apiHost)
/// Provide all the releasable data after a datetime. - POST /productData
/// </summary>
/// <param name="updatesSinceModel">updatesSince Model,pass Null to skip the model</param>
/// <param name="productIdentifier">takes values s101, s102, s104 and s111</param>
/// <param name="sincedateTime">The date and time from which changes are requested which follows RFC1123 format</param>
/// <param name="callbackUri">callbackUri, pass NULL to skip call back notification</param>
/// <param name="accessToken">Access Token, pass NULL to skip auth header</param>
/// <param name="exchangeSetStandard">exchangeSetStandard, pass s63 or s57 for valid exchange set</param>
/// <returns></returns>
public async Task<HttpResponseMessage> GetExchangeSetBasedOnDateTimeAsync(string sincedateTime = null, string callbackUri = null, string accessToken = null, string exchangeSetStandard = "s63", UpdatesSinceModel updatesSinceModel = null)
public async Task<HttpResponseMessage> GetExchangeSetBasedOnDateTimeAsync(string sincedateTime = null, string callbackUri = null, string accessToken = null, string exchangeSetStandard = "s63", UpdatesSinceModel updatesSinceModel = null, string productIdentifier = "")
{
var uri = $"{apiHost}/productData";
var payloadJson = string.Empty;

switch (exchangeSetStandard)
{
case "s100":
uri = $"{apiHost}/v2/exchangeSet/s100/updatesSince";
uri = $"{apiHost}/v2/exchangeSet/s100/updatesSince?productIdentifier={productIdentifier}";
payloadJson = JsonConvert.SerializeObject(updatesSinceModel);
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public static async Task VerifyEssS100ApiResponseBodyDetails(this HttpResponseMe

foreach (var product in responseBody.RequestedProductsNotInExchangeSet)
{
Assert.That(requestedProductsNotInExchangeSet.ContainsKey(product.ProductName),
Assert.That(requestedProductsNotInExchangeSet!.ContainsKey(product.ProductName),
$"Product Name {product.ProductName} not found in requested products not in exchange set.");

var expectedValue = requestedProductsNotInExchangeSet[product.ProductName];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using System;
using System;
using System.Collections.Generic;

namespace UKHO.ExchangeSetService.API.FunctionalTests.Models
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,18 @@
using UKHO.ExchangeSetService.Common.Models;
using UKHO.ExchangeSetService.Common.Models.Enums;
using UKHO.ExchangeSetService.Common.Models.Response;
using UKHO.ExchangeSetService.Common.Models.V2.Enums;
using UKHO.ExchangeSetService.Common.Models.V2.Request;
using UKHO.ExchangeSetService.Common.Models.V2.Response;
using ExchangeSetStandard = UKHO.ExchangeSetService.Common.Models.V2.Enums.ExchangeSetStandard;

namespace UKHO.ExchangeSetService.API.UnitTests.Controllers.V2
{
[TestFixture]
public class ExchangeSetControllerTests
{
private const string CallbackUri = "https://callback.uri";
private const string Iso8601DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fffZ";
private const string ExchangeSetStandard = "s100";
private readonly string _callbackUri = "https://callback.uri";

private IHttpContextAccessor _fakeHttpContextAccessor;
private ILogger<ExchangeSetController> _fakeLogger;
Expand Down Expand Up @@ -77,7 +78,7 @@ public async Task WhenProductNamesIsPassed_ReturnsAcceptedResult()

A.CallTo(() => _fakeHttpContextAccessor.HttpContext.TraceIdentifier).Returns(correlationId);

var response = await _controller.PostProductNames(ExchangeSetStandard, productNames, _callbackUri);
var response = await _controller.PostProductNames(ExchangeSetStandard.s100.ToString(), productNames, CallbackUri);
response.Should().BeOfType<AcceptedResult>().Which.StatusCode.Should().Be(StatusCodes.Status202Accepted);

A.CallTo(_fakeLogger).Where(call => call.Method.Name == "Log"
Expand All @@ -104,7 +105,7 @@ public async Task WhenValidProductVersionsIsPassed_ThenPostProductVersionsReturn
.Returns(ServiceResponseResult<ExchangeSetStandardServiceResponse>
.Accepted(null));

var result = await _controller.PostProductVersions(ExchangeSetStandard, productVersionRequest, _callbackUri);
var result = await _controller.PostProductVersions(ExchangeSetStandard.s100.ToString(), productVersionRequest, CallbackUri);

result.Should().BeOfType<AcceptedResult>().Which.StatusCode.Should().Be(StatusCodes.Status202Accepted);

Expand All @@ -131,7 +132,7 @@ public async Task WhenInvalidProductVersionsIsPassed_ThenPostProductVersionsRetu
A.CallTo(() => _fakeExchangeSetStandardService.ProcessProductVersionsRequestAsync(A<IEnumerable<ProductVersionRequest>>.Ignored, A<ApiVersion>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<CancellationToken>.Ignored))
.Returns(ServiceResponseResult<ExchangeSetStandardServiceResponse>.BadRequest(new ErrorDescription { CorrelationId = Guid.NewGuid().ToString(), Errors = [new() { Source = "requestBody", Description = "Either body is null or malformed." }] }));

var result = await _controller.PostProductVersions(ExchangeSetStandard, productVersionRequest, _callbackUri);
var result = await _controller.PostProductVersions(ExchangeSetStandard.s100.ToString(), productVersionRequest, CallbackUri);

result.Should().BeOfType<BadRequestObjectResult>().Which.StatusCode.Should().Be(StatusCodes.Status400BadRequest);

Expand All @@ -156,10 +157,10 @@ public async Task WhenValidSinceDateTimeRequested_ThenPostUpdatesSinceReturns202
ExchangeSetStandardResponse = GetExchangeSetResponse()
};

A.CallTo(() => _fakeExchangeSetStandardService.ProcessUpdatesSinceRequest(A<UpdatesSinceRequest>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<CancellationToken>.Ignored))
A.CallTo(() => _fakeExchangeSetStandardService.ProcessUpdatesSinceRequestAsync(A<UpdatesSinceRequest>.Ignored, A<ApiVersion>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<CancellationToken>.Ignored))
.Returns(ServiceResponseResult<ExchangeSetStandardServiceResponse>.Accepted(exchangeSetServiceResponse));

var result = await _controller.PostUpdatesSince(ExchangeSetStandard, updatesSinceRequest, "s101", _callbackUri);
var result = await _controller.PostUpdatesSince(ExchangeSetStandard.s100.ToString(), updatesSinceRequest, "s101", CallbackUri);

result.Should().BeOfType<AcceptedResult>().Which.StatusCode.Should().Be(StatusCodes.Status202Accepted);

Expand All @@ -184,10 +185,10 @@ public async Task WhenValidSinceDateTimeAndEmptyProductIdentifierRequested_ThenP
ExchangeSetStandardResponse = GetExchangeSetResponse()
};

A.CallTo(() => _fakeExchangeSetStandardService.ProcessUpdatesSinceRequest(A<UpdatesSinceRequest>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<CancellationToken>.Ignored))
A.CallTo(() => _fakeExchangeSetStandardService.ProcessUpdatesSinceRequestAsync(A<UpdatesSinceRequest>.Ignored, A<ApiVersion>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<CancellationToken>.Ignored))
.Returns(ServiceResponseResult<ExchangeSetStandardServiceResponse>.Accepted(exchangeSetServiceResponse));

var result = await _controller.PostUpdatesSince(ExchangeSetStandard, updatesSinceRequest, "", _callbackUri);
var result = await _controller.PostUpdatesSince(ExchangeSetStandard.s100.ToString(), updatesSinceRequest, "", CallbackUri);

result.Should().BeOfType<AcceptedResult>().Which.StatusCode.Should().Be(StatusCodes.Status202Accepted);

Expand All @@ -205,14 +206,14 @@ public async Task WhenValidSinceDateTimeAndEmptyProductIdentifierRequested_ThenP
[Test]
public async Task WhenNullOrEmptySinceDateTimeRequested_ThenPostUpdatesSinceReturnsBadRequest()
{
A.CallTo(() => _fakeExchangeSetStandardService.ProcessUpdatesSinceRequest(A<UpdatesSinceRequest>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<CancellationToken>.Ignored))
A.CallTo(() => _fakeExchangeSetStandardService.ProcessUpdatesSinceRequestAsync(A<UpdatesSinceRequest>.Ignored, A<ApiVersion>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<CancellationToken>.Ignored))
.Returns(ServiceResponseResult<ExchangeSetStandardServiceResponse>.BadRequest(new ErrorDescription
{
CorrelationId = Guid.NewGuid().ToString(),
Errors = [new() { Source = "requestBody", Description = "Either body is null or malformed." }]
}));

var result = await _controller.PostUpdatesSince(ExchangeSetStandard, null, "s101", _callbackUri);
var result = await _controller.PostUpdatesSince(ExchangeSetStandard.s100.ToString(), null, "s101", CallbackUri);

result.Should().BeOfType<BadRequestObjectResult>().Which.StatusCode.Should().Be(StatusCodes.Status400BadRequest);

Expand All @@ -229,22 +230,21 @@ public async Task WhenNullOrEmptySinceDateTimeRequested_ThenPostUpdatesSinceRetu

[Test]
[TestCase("101", "http://callback.uri")]
[TestCase("101s", "http//callback.uri")]
[TestCase("101s", "http//callback.uri")]
[TestCase("S101", "http:callback.uri")]
public async Task WhenInValidDataRequested_ThenPostUpdatesSinceReturnsBadRequest(string inValidProductIdentifier, string inValidCallBackUri)
{
var updatesSinceRequest = new UpdatesSinceRequest { SinceDateTime = DateTime.UtcNow.AddDays(-10).ToString() };

A.CallTo(() => _fakeExchangeSetStandardService.ProcessUpdatesSinceRequest(A<UpdatesSinceRequest>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<CancellationToken>.Ignored))
A.CallTo(() => _fakeExchangeSetStandardService.ProcessUpdatesSinceRequestAsync(A<UpdatesSinceRequest>.Ignored, A<ApiVersion>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<string>.Ignored, A<CancellationToken>.Ignored))
.Returns(ServiceResponseResult<ExchangeSetStandardServiceResponse>.BadRequest(new ErrorDescription
{
CorrelationId = Guid.NewGuid().ToString(),
Errors = [new() { Source = "SinceDateTime", Description = "Provided sinceDateTime is either invalid or invalid format, the valid format is 'ISO 8601 format' (e.g. '2024-12-20T11:51:00.000Z')." },
new() { Source = "ProductIdentifier", Description = "ProductIdentifier must be valid value" },
new() { Source = "CallbackUri", Description = "Invalid callbackUri format." }]
}));

var result = await _controller.PostUpdatesSince(ExchangeSetStandard, updatesSinceRequest, inValidProductIdentifier, inValidCallBackUri);
var result = await _controller.PostUpdatesSince(ExchangeSetStandard.s100.ToString(), updatesSinceRequest, inValidProductIdentifier, inValidCallBackUri);

result.Should().BeOfType<BadRequestObjectResult>().Which.StatusCode.Should().Be(StatusCodes.Status400BadRequest);

Expand Down
Loading

0 comments on commit 5210ca7

Please sign in to comment.