Skip to content

Commit eef5d95

Browse files
author
Ronaldo Macapobre
committed
- Unit test updates
- Update mapping for base64 to throw exception if value is null
1 parent d18565b commit eef5d95

3 files changed

Lines changed: 419 additions & 2 deletions

File tree

api/Infrastructure/Mappings/OrderMapping.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ public static void Register(TypeAdapterConfig config)
5454
config.NewConfig<OrderDto, JudicialAction>()
5555
.Map(dest => dest.SignatureApplied, src => src.Signed)
5656
.Map(dest => dest.Comment, src => src.Comments)
57-
.Map(dest => dest.Document, src => FromBase64OrNull(
58-
!string.IsNullOrWhiteSpace(src.DocumentData) ? src.DocumentData : src.SupportingDocumentData)).Map(dest => dest.OrderTerms, _ => Array.Empty<OrderTerm>())
57+
.Map(dest => dest.Document, src => FromBase64OrThrow(
58+
!string.IsNullOrWhiteSpace(src.DocumentData) ? src.DocumentData : src.SupportingDocumentData,
59+
nameof(src.DocumentData)))
60+
.Map(dest => dest.OrderTerms, _ => Array.Empty<OrderTerm>())
5961
.AfterMapping((src, dest) =>
6062
{
6163
dest.ActionDate = src.ProcessedDate.HasValue ? src.ProcessedDate.Value : default;
@@ -87,4 +89,21 @@ private static string MapCourtListType(string courtListTypeCode) =>
8789

8890
private static byte[] FromBase64OrNull(string value) =>
8991
string.IsNullOrWhiteSpace(value) ? [] : Convert.FromBase64String(value);
92+
93+
private static byte[] FromBase64OrThrow(string value, string fieldName)
94+
{
95+
if (string.IsNullOrWhiteSpace(value))
96+
{
97+
throw new InvalidOperationException($"'{fieldName}' is required for order submission but was null or empty.");
98+
}
99+
100+
try
101+
{
102+
return Convert.FromBase64String(value);
103+
}
104+
catch (FormatException ex)
105+
{
106+
throw new InvalidOperationException($"'{fieldName}' contains invalid base64 content and cannot be decoded.", ex);
107+
}
108+
}
90109
}
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Security.Claims;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using CSOCommon.Clients.JudicialServices;
7+
using CSOCommon.Models;
8+
using Microsoft.AspNetCore.WebUtilities;
9+
using Microsoft.Extensions.Configuration;
10+
using Moq;
11+
using Nutrient.NativeSDK.API.Exceptions;
12+
using Scv.Api.Documents.Strategies;
13+
using Scv.Core.Helpers;
14+
using Scv.Models.Document;
15+
using tests.api.Services;
16+
using Xunit;
17+
18+
namespace tests.api.Documents.Strategies;
19+
20+
public class OrderDocumentStrategyTest : ServiceTestBase
21+
{
22+
private readonly Mock<IJudicialServicesClient> _mockJudicialClient;
23+
private readonly Mock<IConfiguration> _mockConfiguration;
24+
private readonly string _fakeContent = "fake-pdf-bytes";
25+
private readonly byte[] _fakeContentBytes;
26+
27+
public OrderDocumentStrategyTest()
28+
{
29+
_fakeContentBytes = Encoding.UTF8.GetBytes(_fakeContent);
30+
_mockJudicialClient = new Mock<IJudicialServicesClient>();
31+
_mockConfiguration = new Mock<IConfiguration>();
32+
33+
var mockAgencySection = Mock.Of<IConfigurationSection>(s => s.Value == "123");
34+
var mockAppCdSection = Mock.Of<IConfigurationSection>(s => s.Value == "TESTAPP");
35+
36+
_mockConfiguration
37+
.Setup(c => c.GetSection("Request:AgencyIdentifierId"))
38+
.Returns(mockAgencySection);
39+
_mockConfiguration
40+
.Setup(c => c.GetSection("Request:ApplicationCd"))
41+
.Returns(mockAppCdSection);
42+
43+
_mockJudicialClient.Setup(j => j.JsonSerializerSettings).Returns(new Newtonsoft.Json.JsonSerializerSettings());
44+
}
45+
46+
private static ClaimsPrincipal BuildUser(string provjudGuid = null, string idirGuid = null)
47+
{
48+
var claims = new List<Claim>();
49+
if (provjudGuid != null)
50+
{
51+
claims.Add(new Claim(CustomClaimTypes.ProvjudUserGuid, provjudGuid));
52+
}
53+
if (idirGuid != null)
54+
{
55+
claims.Add(new Claim(CustomClaimTypes.UserGuid, idirGuid));
56+
}
57+
58+
return new ClaimsPrincipal(new ClaimsIdentity(claims, "test"));
59+
}
60+
61+
private PdfDocumentRequestDetails BuildRequest(string rawDocumentId = "12345", string correlationId = null)
62+
{
63+
var encoded = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(rawDocumentId));
64+
return new PdfDocumentRequestDetails
65+
{
66+
DocumentId = encoded,
67+
CorrelationId = correlationId
68+
};
69+
}
70+
71+
private void SetupJudicialClientResponse()
72+
{
73+
var fakeStream = new MemoryStream(_fakeContentBytes);
74+
var fakeResponse = new FileResponse(
75+
200,
76+
new Dictionary<string, IEnumerable<string>>(),
77+
fakeStream,
78+
null,
79+
null);
80+
81+
_mockJudicialClient
82+
.Setup(c => c.GetJudicialDocumentAsync(
83+
It.IsAny<System.Guid>(),
84+
It.IsAny<double?>(),
85+
It.IsAny<double>(),
86+
It.IsAny<DocumentApplicationName>(),
87+
It.IsAny<string>(),
88+
It.IsAny<string>(),
89+
It.IsAny<string>()))
90+
.ReturnsAsync(fakeResponse);
91+
}
92+
93+
[Fact]
94+
public void Type_ReturnsOrder()
95+
{
96+
var strategy = new OrderDocumentStrategy(
97+
_mockJudicialClient.Object,
98+
_mockConfiguration.Object,
99+
BuildUser());
100+
101+
Assert.Equal(DocumentType.Order, strategy.Type);
102+
}
103+
104+
[Fact]
105+
public async Task Invoke_ReturnsMemoryStreamWithDocumentContent()
106+
{
107+
SetupJudicialClientResponse();
108+
var user = BuildUser();
109+
var strategy = new OrderDocumentStrategy(
110+
_mockJudicialClient.Object,
111+
_mockConfiguration.Object,
112+
user);
113+
114+
var result = await strategy.Invoke(BuildRequest());
115+
116+
Assert.NotNull(result);
117+
result.Position = 0;
118+
Assert.Equal(_fakeContentBytes, result.ToArray());
119+
}
120+
121+
[Fact]
122+
public async Task Invoke_AssignsCorrelationId_WhenNotProvided()
123+
{
124+
SetupJudicialClientResponse();
125+
var request = BuildRequest(correlationId: null);
126+
var strategy = new OrderDocumentStrategy(
127+
_mockJudicialClient.Object,
128+
_mockConfiguration.Object,
129+
BuildUser());
130+
131+
await strategy.Invoke(request);
132+
133+
Assert.NotNull(request.CorrelationId);
134+
Assert.True(System.Guid.TryParse(request.CorrelationId, out _));
135+
}
136+
137+
[Fact]
138+
public async Task Invoke_PreservesCorrelationId_WhenAlreadyProvided()
139+
{
140+
SetupJudicialClientResponse();
141+
var request = BuildRequest(correlationId: "existing-correlation-id");
142+
var strategy = new OrderDocumentStrategy(
143+
_mockJudicialClient.Object,
144+
_mockConfiguration.Object,
145+
BuildUser());
146+
147+
await strategy.Invoke(request);
148+
149+
Assert.Equal("existing-correlation-id", request.CorrelationId);
150+
}
151+
152+
[Fact]
153+
public async Task Invoke_ThrowsInvalidArgumentException_WhenDocumentIdIsNull()
154+
{
155+
var request = new PdfDocumentRequestDetails { DocumentId = null };
156+
var strategy = new OrderDocumentStrategy(
157+
_mockJudicialClient.Object,
158+
_mockConfiguration.Object,
159+
BuildUser());
160+
161+
await Assert.ThrowsAsync<InvalidArgumentException>(() => strategy.Invoke(request));
162+
}
163+
164+
[Fact]
165+
public async Task Invoke_ThrowsInvalidArgumentException_WhenDocumentIdIsNotValidBase64Number()
166+
{
167+
var encoded = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes("not-a-number"));
168+
var request = new PdfDocumentRequestDetails { DocumentId = encoded };
169+
var strategy = new OrderDocumentStrategy(
170+
_mockJudicialClient.Object,
171+
_mockConfiguration.Object,
172+
BuildUser());
173+
174+
await Assert.ThrowsAsync<InvalidArgumentException>(() => strategy.Invoke(request));
175+
}
176+
177+
[Fact]
178+
public async Task Invoke_ThrowsInvalidArgumentException_WhenAgencyIdIsInvalid()
179+
{
180+
var badAgencySection = Mock.Of<IConfigurationSection>(s => s.Value == "not-a-number");
181+
_mockConfiguration
182+
.Setup(c => c.GetSection("Request:AgencyIdentifierId"))
183+
.Returns(badAgencySection);
184+
185+
var strategy = new OrderDocumentStrategy(
186+
_mockJudicialClient.Object,
187+
_mockConfiguration.Object,
188+
BuildUser());
189+
190+
await Assert.ThrowsAsync<InvalidArgumentException>(() => strategy.Invoke(BuildRequest()));
191+
}
192+
193+
[Fact]
194+
public async Task Invoke_UsesProvjudGuid_WhenAvailable()
195+
{
196+
SetupJudicialClientResponse();
197+
198+
// ProvjudUserGuid extension decodes from base64, so encode a fake GUID bytes
199+
var fakeGuidBytes = System.Guid.NewGuid().ToByteArray();
200+
var base64Guid = System.Convert.ToBase64String(fakeGuidBytes);
201+
var expectedHex = System.Convert.ToHexStringLower(fakeGuidBytes);
202+
203+
var user = BuildUser(provjudGuid: base64Guid);
204+
var strategy = new OrderDocumentStrategy(
205+
_mockJudicialClient.Object,
206+
_mockConfiguration.Object,
207+
user);
208+
209+
await strategy.Invoke(BuildRequest());
210+
211+
_mockJudicialClient.Verify(c => c.GetJudicialDocumentAsync(
212+
It.IsAny<System.Guid>(),
213+
It.IsAny<double?>(),
214+
It.IsAny<double>(),
215+
It.IsAny<DocumentApplicationName>(),
216+
It.IsAny<string>(),
217+
It.IsAny<string>(),
218+
expectedHex.ToUpper()), Times.Once);
219+
}
220+
}

0 commit comments

Comments
 (0)