Skip to content
This repository was archived by the owner on Jul 28, 2025. It is now read-only.

Commit 48e068c

Browse files
feat: Introduced validation attribute for DateOnly to have better control over error messages
1 parent 5fec2b3 commit 48e068c

File tree

4 files changed

+47
-2
lines changed

4 files changed

+47
-2
lines changed

src/ServiceLayer.API/Functions/BSSelectFunctions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public async Task<IActionResult> IngressEpisode([HttpTrigger(AuthorizationLevel.
4646
PathwayTypeName = "Breast Screening Routine",
4747
ScreeningName = "Breast Screening",
4848
NhsNumber = bssEpisodeEvent.NhsNumber!,
49-
DOB = (DateOnly)bssEpisodeEvent.DateOfBirth!,
49+
DOB = DateOnly.Parse(bssEpisodeEvent.DateOfBirth!),
5050
Name = $"{bssEpisodeEvent.FirstGivenName} {bssEpisodeEvent.FamilyName}",
5151
};
5252

src/ServiceLayer.API/Models/BSSelectEpisode.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.ComponentModel.DataAnnotations;
22
using System.Text.Json.Serialization;
3+
using ServiceLayer.API.Shared;
34

45
namespace ServiceLayer.API.Models;
56

@@ -16,7 +17,8 @@ public class BSSelectEpisode
1617

1718
[JsonPropertyName("date_of_birth")]
1819
[Required(ErrorMessage = "date_of_birth is required")]
19-
public DateOnly? DateOfBirth { get; set; }
20+
[ValidDateOnly(ErrorMessage = "date_of_birth is invalid")]
21+
public string? DateOfBirth { get; set; }
2022

2123
[JsonPropertyName("first_given_name")]
2224
[Required(ErrorMessage = "first_given_name is required")]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace ServiceLayer.API.Shared;
4+
5+
public class ValidDateOnlyAttribute : ValidationAttribute
6+
{
7+
public override bool IsValid(object? value)
8+
{
9+
if (value is string s && DateOnly.TryParse(s, out _))
10+
{
11+
return true;
12+
}
13+
14+
return false;
15+
}
16+
}

tests/ServiceLayer.API.Tests/Functions/BSSelectFunctionsTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ public async Task CreateEpisodeEvent_ShouldReturnBadRequest_WhenDateOfBirthIsMis
207207

208208
[Theory]
209209
[InlineData(null)]
210+
[InlineData("")]
211+
[InlineData(" ")]
210212
public async Task CreateEpisodeEvent_ShouldReturnBadRequest_WhenDateOfBirthIsEmptyValue(string? dateOfBirth)
211213
{
212214
// Arrange
@@ -229,6 +231,31 @@ public async Task CreateEpisodeEvent_ShouldReturnBadRequest_WhenDateOfBirthIsEmp
229231
_mockEventGridPublisherClient.Verify(x => x.SendEventAsync(It.IsAny<CloudEvent>(), It.IsAny<CancellationToken>()), Times.Never());
230232
}
231233

234+
[Theory]
235+
[InlineData("ABC")]
236+
[InlineData("123")]
237+
public async Task CreateEpisodeEvent_ShouldReturnBadRequest_WhenDateOfBirthIsInvalidValue(string? dateOfBirth)
238+
{
239+
// Arrange
240+
var episode = new
241+
{
242+
episode_id = "123",
243+
nhs_number = "9990000000",
244+
date_of_birth = dateOfBirth,
245+
first_given_name = "Test",
246+
family_name = "User",
247+
};
248+
var request = _setupRequest.CreateMockHttpRequest(episode);
249+
250+
// Act
251+
var response = await _functions.IngressEpisode(request);
252+
253+
// Assert
254+
var result = Assert.IsType<BadRequestObjectResult>(response);
255+
Assert.Equal("date_of_birth is invalid", result.Value);
256+
_mockEventGridPublisherClient.Verify(x => x.SendEventAsync(It.IsAny<CloudEvent>(), It.IsAny<CancellationToken>()), Times.Never());
257+
}
258+
232259
[Fact]
233260
public async Task CreateEpisodeEvent_ShouldReturnBadRequest_WhenFirstGivenNameIsMissing()
234261
{

0 commit comments

Comments
 (0)