Skip to content

Commit aee9690

Browse files
abhishekkumamssezalchug
and
sezalchug
authored
Fix Json Schema validations for optional fields (#2611)
## Why make this change? - Closes #2542 - Schema validation is incorrectly raising failure when optional fields are not present. - This change will ensure optional fields are correctly evaluated during schema validation. ## What is this change? - updated the `dab.draft.schema.json` optional field types with `null` to allow for optional fields to be evaluated correctly during schema validation. ## How was this tested? - [X] Manual Tests - [X] Unit Tests ## Sample Request(s) config: ![image](https://github.com/user-attachments/assets/e93f83a4-0552-4471-b364-3dd095ab7fba) Before Fix: ![image](https://github.com/user-attachments/assets/5c6ba6c6-1ba5-465f-ac1f-b4e3b1d08b24) After Fix: ![image](https://github.com/user-attachments/assets/c6135189-0cad-44c2-bb5d-eb588d115c6a) --------- Co-authored-by: sezalchug <[email protected]>
1 parent 5b3a471 commit aee9690

File tree

2 files changed

+124
-3
lines changed

2 files changed

+124
-3
lines changed

schemas/dab.draft.schema.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -245,15 +245,15 @@
245245
},
246246
"mode": {
247247
"description": "Set if running in Development or Production mode",
248-
"type": "string",
248+
"type": ["string", "null"],
249249
"default": "production",
250250
"enum": [
251251
"production",
252252
"development"
253253
]
254254
},
255255
"cors": {
256-
"type": "object",
256+
"type": ["object", "null"],
257257
"description": "Configure CORS",
258258
"additionalProperties": false,
259259
"properties": {
@@ -273,7 +273,7 @@
273273
}
274274
},
275275
"authentication": {
276-
"type": "object",
276+
"type": ["object", "null"],
277277
"additionalProperties": false,
278278
"properties": {
279279
"provider": {

src/Service.Tests/Configuration/ConfigurationTests.cs

+121
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,69 @@ type Moon {
467467
}
468468
";
469469

470+
public const string CONFIG_FILE_WITH_NO_OPTIONAL_FIELD = @"{
471+
""$schema"":""https://github.com/Azure/data-api-builder/releases/download/vmajor.minor.patch-alpha/dab.draft.schema.json"",
472+
""data-source"": {
473+
""database-type"": ""mssql"",
474+
""connection-string"": ""sample-conn-string""
475+
},
476+
""entities"":{ }
477+
}";
478+
479+
public const string CONFIG_FILE_WITH_NO_AUTHENTICATION_FIELD = @"{
480+
// Link for latest draft schema.
481+
""$schema"":""https://github.com/Azure/data-api-builder/releases/download/vmajor.minor.patch-alpha/dab.draft.schema.json"",
482+
""data-source"": {
483+
""database-type"": ""mssql"",
484+
""connection-string"": ""sample-conn-string""
485+
},
486+
""runtime"": {
487+
""rest"": {
488+
""enabled"": true,
489+
""path"": ""/api""
490+
},
491+
""graphql"": {
492+
""enabled"": true,
493+
""path"": ""/graphql"",
494+
""allow-introspection"": true
495+
},
496+
""host"": {
497+
""cors"": {
498+
""origins"": [
499+
""http://localhost:5000""
500+
],
501+
""allow-credentials"": false
502+
}
503+
}
504+
},
505+
""entities"":{ }
506+
}";
507+
public const string CONFIG_FILE_WITH_NO_CORS_FIELD = @"{
508+
// Link for latest draft schema.
509+
""$schema"":""https://github.com/Azure/data-api-builder/releases/download/vmajor.minor.patch-alpha/dab.draft.schema.json"",
510+
""data-source"": {
511+
""database-type"": ""mssql"",
512+
""connection-string"": ""sample-conn-string""
513+
},
514+
""runtime"": {
515+
""rest"": {
516+
""enabled"": true,
517+
""path"": ""/api""
518+
},
519+
""graphql"": {
520+
""enabled"": true,
521+
""path"": ""/graphql"",
522+
""allow-introspection"": true
523+
},
524+
""host"": {
525+
""authentication"": {
526+
""provider"": ""StaticWebApps""
527+
}
528+
}
529+
},
530+
""entities"":{ }
531+
}";
532+
470533
[TestCleanup]
471534
public void CleanupAfterEachTest()
472535
{
@@ -1590,6 +1653,64 @@ public async Task TestConfigSchemaIsValid()
15901653
Times.Once);
15911654
}
15921655

1656+
/// <summary>
1657+
/// This test method validates a sample DAB runtime config file against DAB's JSON schema definition.
1658+
/// It asserts that the validation is successful and there are no validation failures when no optional fields are used.
1659+
/// It also verifies that the expected log message is logged.
1660+
/// </summary>
1661+
[DataTestMethod]
1662+
[DataRow(CONFIG_FILE_WITH_NO_OPTIONAL_FIELD, DisplayName = "Validates schema of the config file with no optional fields.")]
1663+
[DataRow(CONFIG_FILE_WITH_NO_AUTHENTICATION_FIELD, DisplayName = "Validates schema of the config file with no Authentication field.")]
1664+
[DataRow(CONFIG_FILE_WITH_NO_CORS_FIELD, DisplayName = "Validates schema of the config file with no Cors field.")]
1665+
public async Task TestBasicConfigSchemaWithNoOptionalFieldsIsValid(string jsonData)
1666+
{
1667+
Mock<ILogger<JsonConfigSchemaValidator>> schemaValidatorLogger = new();
1668+
1669+
string jsonSchema = File.ReadAllText("dab.draft.schema.json");
1670+
1671+
JsonConfigSchemaValidator jsonSchemaValidator = new(schemaValidatorLogger.Object, new MockFileSystem());
1672+
1673+
JsonSchemaValidationResult result = await jsonSchemaValidator.ValidateJsonConfigWithSchemaAsync(jsonSchema, jsonData);
1674+
Assert.IsTrue(result.IsValid);
1675+
Assert.IsTrue(EnumerableUtilities.IsNullOrEmpty(result.ValidationErrors));
1676+
schemaValidatorLogger.Verify(
1677+
x => x.Log(
1678+
LogLevel.Information,
1679+
It.IsAny<EventId>(),
1680+
It.Is<It.IsAnyType>((o, t) => o.ToString()!.Contains($"The config satisfies the schema requirements.")),
1681+
It.IsAny<Exception>(),
1682+
(Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
1683+
Times.Once);
1684+
}
1685+
1686+
/// <summary>
1687+
/// The config file does not contain any entity fields, which is expected to be invalid according to the schema.
1688+
/// The test asserts that the validation fails and there are validation errors.
1689+
/// It also verifies that the expected error message is logged, indicating that the 'entities' property is required.
1690+
[TestMethod]
1691+
public async Task TestBasicConfigSchemaWithNoEntityFieldsIsInvalid()
1692+
{
1693+
string jsonData = @"{
1694+
""$schema"":""https://github.com/Azure/data-api-builder/releases/download/vmajor.minor.patch-alpha/dab.draft.schema.json"",
1695+
""data-source"": {
1696+
""database-type"": ""mssql"",
1697+
""connection-string"": ""sample-conn-string""
1698+
}
1699+
}";
1700+
1701+
Mock<ILogger<JsonConfigSchemaValidator>> schemaValidatorLogger = new();
1702+
1703+
string jsonSchema = File.ReadAllText("dab.draft.schema.json");
1704+
1705+
JsonConfigSchemaValidator jsonSchemaValidator = new(schemaValidatorLogger.Object, new MockFileSystem());
1706+
1707+
JsonSchemaValidationResult result = await jsonSchemaValidator.ValidateJsonConfigWithSchemaAsync(jsonSchema, jsonData);
1708+
Assert.IsFalse(result.IsValid);
1709+
Assert.IsFalse(EnumerableUtilities.IsNullOrEmpty(result.ValidationErrors));
1710+
Assert.AreEqual(1, result.ErrorCount);
1711+
Assert.IsTrue(result.ErrorMessage.Contains("Total schema validation errors: 1\n> PropertyRequired: #/entities"));
1712+
}
1713+
15931714
/// <summary>
15941715
/// This test tries to validate a runtime config file that is not compliant with the runtime config JSON schema.
15951716
/// It validates no additional properties are defined in the config file.

0 commit comments

Comments
 (0)