From d260ff55b468081eaa973c417b239a14f4034020 Mon Sep 17 00:00:00 2001 From: souvikghosh04 Date: Tue, 4 Aug 2026 13:44:00 +0530 Subject: [PATCH 1/3] test(mssql-json): add malformed-JSON (400) and filter pass-through tests (Phase 4) Covers the JSON error-handling and filter user stories from #2768: - US7 REST: InsertMalformedJson_ReturnsBadRequest - posting invalid JSON for the json column is rejected by SQL Server and surfaced as HTTP 400 (not 500), exercising the 13608-13614 -> BadRequest mapping. - US7 GraphQL: JsonColumn_GraphQLCreateWithMalformedJson_Fails - a createProfile mutation with malformed JSON fails with a GraphQL error (mirrors the merged vector-type pattern). - US9 REST: FilterJsonColumnIsNotNull_Succeeds - filtering a json column as a string (metadata ne null) passes through to SQL and returns the 4 non-null rows. --- .../MsSqlGraphQLJsonSchemaTests.cs | 20 +++++++++++ .../RestApiTests/MsSqlRestJsonTypesTests.cs | 35 +++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs index 66ee6156a7..00ae140f37 100644 --- a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs +++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs @@ -82,5 +82,25 @@ public async Task JsonColumn_GraphQLRead_ReturnsPayloadAsString() Assert.AreEqual("admin", parsed.GetProperty("role").GetString()); Assert.AreEqual(3, parsed.GetProperty("tier").GetInt32()); } + + /// + /// createProfile with malformed JSON in the metadata field must fail with a GraphQL error + /// (surfaced from SQL Server's json validation) rather than persisting invalid data. + /// + [TestMethod] + public async Task JsonColumn_GraphQLCreateWithMalformedJson_Fails() + { + string createMutationName = "createProfile"; + string createMutation = @"mutation { + createProfile(item: { metadata: ""{ not valid json"" }) { + id + metadata + } + }"; + + JsonElement result = await ExecuteGraphQLRequestAsync(createMutation, createMutationName, isAuthenticated: false, expectsError: true); + + SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString()); + } } } diff --git a/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs b/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs index 8e8c20417d..04e149c3d1 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs @@ -114,6 +114,21 @@ public async Task GetJsonTypeWithUnicode() Assert.AreEqual("éü😀", metadata.GetProperty("unicode").GetString()); } + /// + /// GET /api/Profile?$filter=metadata ne null - Verify filtering a json column (treated as a + /// string) passes through to SQL: the 4 non-null rows match and the null row (id 5) does not. + /// + [TestMethod] + public async Task FilterJsonColumnIsNotNull_Succeeds() + { + HttpResponseMessage response = await HttpClient.GetAsync($"{JSON_TYPE_REST_PATH}?$filter=metadata ne null"); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Filtering a json column as a string should pass through and succeed."); + + JsonElement items = JsonDocument.Parse(await response.Content.ReadAsStringAsync()) + .RootElement.GetProperty("value"); + Assert.AreEqual(4, items.GetArrayLength(), "Only the 4 rows with non-null metadata should match."); + } + #endregion #region Write Tests @@ -221,6 +236,26 @@ public async Task PatchJsonType_ToNull() } } + /// + /// POST /api/Profile - Verify that supplying invalid JSON for the json column is rejected by + /// SQL Server and surfaced as HTTP 400 (a client input error), not a 500. DAB treats the value + /// as a normal string, so JSON validation happens at the database boundary. + /// + [DataTestMethod] + [DataRow("{ \"metadata\": \"{ not valid json\" }", DisplayName = "Unclosed / unquoted object")] + [DataRow("{ \"metadata\": \"{\\\"key\\\": }\" }", DisplayName = "Missing value")] + public async Task InsertMalformedJson_ReturnsBadRequest(string requestBody) + { + HttpResponseMessage response = await HttpClient.PostAsync( + JSON_TYPE_REST_PATH, + new StringContent(requestBody, Encoding.UTF8, "application/json")); + + Assert.AreEqual( + HttpStatusCode.BadRequest, + response.StatusCode, + "SQL Server rejects invalid JSON for a native json column; DAB must surface it as HTTP 400."); + } + #endregion #region Helpers From cb44e97243762a8cca1bb54f3d64c4381338f43a Mon Sep 17 00:00:00 2001 From: Souvik Ghosh Date: Tue, 4 Aug 2026 14:07:27 +0530 Subject: [PATCH 2/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs b/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs index 04e149c3d1..04d2addfab 100644 --- a/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs +++ b/src/Service.Tests/SqlTests/RestApiTests/MsSqlRestJsonTypesTests.cs @@ -121,7 +121,7 @@ public async Task GetJsonTypeWithUnicode() [TestMethod] public async Task FilterJsonColumnIsNotNull_Succeeds() { - HttpResponseMessage response = await HttpClient.GetAsync($"{JSON_TYPE_REST_PATH}?$filter=metadata ne null"); + HttpResponseMessage response = await HttpClient.GetAsync($"{JSON_TYPE_REST_PATH}?$filter=metadata%20ne%20null"); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Filtering a json column as a string should pass through and succeed."); JsonElement items = JsonDocument.Parse(await response.Content.ReadAsStringAsync()) From 7f651dd1a39bb817a85d4b608d0da91fb0a17dbb Mon Sep 17 00:00:00 2001 From: Souvik Ghosh Date: Tue, 4 Aug 2026 14:07:40 +0530 Subject: [PATCH 3/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs index 00ae140f37..54dc30e753 100644 --- a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs +++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLJsonSchemaTests.cs @@ -98,9 +98,10 @@ public async Task JsonColumn_GraphQLCreateWithMalformedJson_Fails() } }"; - JsonElement result = await ExecuteGraphQLRequestAsync(createMutation, createMutationName, isAuthenticated: false, expectsError: true); + JsonElement errors = await ExecuteGraphQLRequestAsync(createMutation, createMutationName, isAuthenticated: false); - SqlTestHelper.TestForErrorInGraphQLResponse(result.ToString()); + Assert.AreEqual(JsonValueKind.Array, errors.ValueKind, "Expected a GraphQL errors array for malformed JSON payload."); + Assert.IsTrue(errors.GetArrayLength() > 0, "Expected at least one GraphQL error."); } } }