diff --git a/NEW/tests/JdeScoping.Database.Tests/Procedures/ValidateSearchCriteriaProcedureTests.cs b/NEW/tests/JdeScoping.Database.Tests/Procedures/ValidateSearchCriteriaProcedureTests.cs
new file mode 100644
index 0000000..9148b73
--- /dev/null
+++ b/NEW/tests/JdeScoping.Database.Tests/Procedures/ValidateSearchCriteriaProcedureTests.cs
@@ -0,0 +1,111 @@
+using Dapper;
+using FluentAssertions;
+using JdeScoping.Core.Models.Search;
+using JdeScoping.Database.Tests.Infrastructure;
+using Microsoft.Data.SqlClient;
+
+namespace JdeScoping.Database.Tests.Procedures;
+
+///
+/// Tests for usp_ValidateSearchCriteria stored procedure.
+/// Validates that the procedure throws appropriate errors for invalid search criteria.
+///
+[Collection("DatabaseTests")]
+public class ValidateSearchCriteriaProcedureTests : DatabaseTestBase
+{
+ [Fact]
+ public async Task usp_ValidateSearchCriteria_ValidSearch_Succeeds()
+ {
+ // Arrange
+ var criteria = new SearchCriteria { WorkOrderNumbers = [12345] };
+ var searchId = await InsertTestSearchAsync(criteria);
+
+ // Act
+ var act = async () => await Connection.ExecuteAsync(
+ "EXEC dbo.usp_ValidateSearchCriteria @SearchId",
+ new { SearchId = searchId });
+
+ // Assert
+ await act.Should().NotThrowAsync();
+ }
+
+ [Fact]
+ public async Task usp_ValidateSearchCriteria_SearchNotFound_ThrowsError50001()
+ {
+ // Act
+ var act = async () => await Connection.ExecuteAsync(
+ "EXEC dbo.usp_ValidateSearchCriteria @SearchId",
+ new { SearchId = 99999 });
+
+ // Assert
+ var ex = await act.Should().ThrowAsync();
+ ex.Which.Number.Should().Be(50001);
+ ex.Which.Message.Should().Contain("Search ID 99999 not found");
+ }
+
+ [Fact]
+ public async Task usp_ValidateSearchCriteria_NullCriteria_ThrowsError50002()
+ {
+ // Arrange
+ var searchId = await InsertTestSearchWithRawCriteriaAsync(null);
+
+ // Act
+ var act = async () => await Connection.ExecuteAsync(
+ "EXEC dbo.usp_ValidateSearchCriteria @SearchId",
+ new { SearchId = searchId });
+
+ // Assert
+ var ex = await act.Should().ThrowAsync();
+ ex.Which.Number.Should().Be(50002);
+ ex.Which.Message.Should().Contain("has no criteria");
+ }
+
+ [Fact]
+ public async Task usp_ValidateSearchCriteria_EmptyCriteria_ThrowsError50002()
+ {
+ // Arrange
+ var searchId = await InsertTestSearchWithRawCriteriaAsync("");
+
+ // Act
+ var act = async () => await Connection.ExecuteAsync(
+ "EXEC dbo.usp_ValidateSearchCriteria @SearchId",
+ new { SearchId = searchId });
+
+ // Assert
+ var ex = await act.Should().ThrowAsync();
+ ex.Which.Number.Should().Be(50002);
+ ex.Which.Message.Should().Contain("has no criteria");
+ }
+
+ [Fact]
+ public async Task usp_ValidateSearchCriteria_InvalidJson_ThrowsError50003()
+ {
+ // Arrange
+ var searchId = await InsertTestSearchWithRawCriteriaAsync("not valid json {{{");
+
+ // Act
+ var act = async () => await Connection.ExecuteAsync(
+ "EXEC dbo.usp_ValidateSearchCriteria @SearchId",
+ new { SearchId = searchId });
+
+ // Assert
+ var ex = await act.Should().ThrowAsync();
+ ex.Which.Number.Should().Be(50003);
+ ex.Which.Message.Should().Contain("has invalid JSON");
+ }
+
+ [Fact]
+ public async Task usp_ValidateSearchCriteria_EmptyJsonObject_Succeeds()
+ {
+ // Arrange - empty JSON object is valid
+ var searchId = await InsertTestSearchWithRawCriteriaAsync("{}");
+
+ // Act
+ var act = async () => await Connection.ExecuteAsync(
+ "EXEC dbo.usp_ValidateSearchCriteria @SearchId",
+ new { SearchId = searchId });
+
+ // Assert
+ await act.Should().NotThrowAsync();
+ }
+}