diff --git a/schemas/dab.draft.schema.json b/schemas/dab.draft.schema.json index 58132c088f..08d220298b 100644 --- a/schemas/dab.draft.schema.json +++ b/schemas/dab.draft.schema.json @@ -245,7 +245,7 @@ }, "mode": { "description": "Set if running in Development or Production mode", - "type": "string", + "type": ["string", "null"], "default": "production", "enum": [ "production", @@ -253,7 +253,7 @@ ] }, "cors": { - "type": "object", + "type": ["object", "null"], "description": "Configure CORS", "additionalProperties": false, "properties": { @@ -273,7 +273,7 @@ } }, "authentication": { - "type": "object", + "type": ["object", "null"], "additionalProperties": false, "properties": { "provider": { diff --git a/src/Service.Tests/Configuration/ConfigurationTests.cs b/src/Service.Tests/Configuration/ConfigurationTests.cs index 052a6434ed..d9d7f53f19 100644 --- a/src/Service.Tests/Configuration/ConfigurationTests.cs +++ b/src/Service.Tests/Configuration/ConfigurationTests.cs @@ -467,6 +467,69 @@ type Moon { } "; + public const string CONFIG_FILE_WITH_NO_OPTIONAL_FIELD = @"{ + ""$schema"":""https://github.com/Azure/data-api-builder/releases/download/vmajor.minor.patch-alpha/dab.draft.schema.json"", + ""data-source"": { + ""database-type"": ""mssql"", + ""connection-string"": ""sample-conn-string"" + }, + ""entities"":{ } + }"; + + public const string CONFIG_FILE_WITH_NO_AUTHENTICATION_FIELD = @"{ + // Link for latest draft schema. + ""$schema"":""https://github.com/Azure/data-api-builder/releases/download/vmajor.minor.patch-alpha/dab.draft.schema.json"", + ""data-source"": { + ""database-type"": ""mssql"", + ""connection-string"": ""sample-conn-string"" + }, + ""runtime"": { + ""rest"": { + ""enabled"": true, + ""path"": ""/api"" + }, + ""graphql"": { + ""enabled"": true, + ""path"": ""/graphql"", + ""allow-introspection"": true + }, + ""host"": { + ""cors"": { + ""origins"": [ + ""http://localhost:5000"" + ], + ""allow-credentials"": false + } + } + }, + ""entities"":{ } + }"; + public const string CONFIG_FILE_WITH_NO_CORS_FIELD = @"{ + // Link for latest draft schema. + ""$schema"":""https://github.com/Azure/data-api-builder/releases/download/vmajor.minor.patch-alpha/dab.draft.schema.json"", + ""data-source"": { + ""database-type"": ""mssql"", + ""connection-string"": ""sample-conn-string"" + }, + ""runtime"": { + ""rest"": { + ""enabled"": true, + ""path"": ""/api"" + }, + ""graphql"": { + ""enabled"": true, + ""path"": ""/graphql"", + ""allow-introspection"": true + }, + ""host"": { + ""authentication"": { + ""provider"": ""StaticWebApps"" + } + } + }, + ""entities"":{ } + }"; + [TestCleanup] public void CleanupAfterEachTest() { @@ -1590,6 +1653,64 @@ public async Task TestConfigSchemaIsValid() Times.Once); } + /// + /// This test method validates a sample DAB runtime config file against DAB's JSON schema definition. + /// It asserts that the validation is successful and there are no validation failures when no optional fields are used. + /// It also verifies that the expected log message is logged. + /// + [DataTestMethod] + [DataRow(CONFIG_FILE_WITH_NO_OPTIONAL_FIELD, DisplayName = "Validates schema of the config file with no optional fields.")] + [DataRow(CONFIG_FILE_WITH_NO_AUTHENTICATION_FIELD, DisplayName = "Validates schema of the config file with no Authentication field.")] + [DataRow(CONFIG_FILE_WITH_NO_CORS_FIELD, DisplayName = "Validates schema of the config file with no Cors field.")] + public async Task TestBasicConfigSchemaWithNoOptionalFieldsIsValid(string jsonData) + { + Mock> schemaValidatorLogger = new(); + + string jsonSchema = File.ReadAllText("dab.draft.schema.json"); + + JsonConfigSchemaValidator jsonSchemaValidator = new(schemaValidatorLogger.Object, new MockFileSystem()); + + JsonSchemaValidationResult result = await jsonSchemaValidator.ValidateJsonConfigWithSchemaAsync(jsonSchema, jsonData); + Assert.IsTrue(result.IsValid); + Assert.IsTrue(EnumerableUtilities.IsNullOrEmpty(result.ValidationErrors)); + schemaValidatorLogger.Verify( + x => x.Log( + LogLevel.Information, + It.IsAny(), + It.Is((o, t) => o.ToString()!.Contains($"The config satisfies the schema requirements.")), + It.IsAny(), + (Func)It.IsAny()), + Times.Once); + } + + /// + /// The config file does not contain any entity fields, which is expected to be invalid according to the schema. + /// The test asserts that the validation fails and there are validation errors. + /// It also verifies that the expected error message is logged, indicating that the 'entities' property is required. + [TestMethod] + public async Task TestBasicConfigSchemaWithNoEntityFieldsIsInvalid() + { + string jsonData = @"{ + ""$schema"":""https://github.com/Azure/data-api-builder/releases/download/vmajor.minor.patch-alpha/dab.draft.schema.json"", + ""data-source"": { + ""database-type"": ""mssql"", + ""connection-string"": ""sample-conn-string"" + } + }"; + + Mock> schemaValidatorLogger = new(); + + string jsonSchema = File.ReadAllText("dab.draft.schema.json"); + + JsonConfigSchemaValidator jsonSchemaValidator = new(schemaValidatorLogger.Object, new MockFileSystem()); + + JsonSchemaValidationResult result = await jsonSchemaValidator.ValidateJsonConfigWithSchemaAsync(jsonSchema, jsonData); + Assert.IsFalse(result.IsValid); + Assert.IsFalse(EnumerableUtilities.IsNullOrEmpty(result.ValidationErrors)); + Assert.AreEqual(1, result.ErrorCount); + Assert.IsTrue(result.ErrorMessage.Contains("Total schema validation errors: 1\n> PropertyRequired: #/entities")); + } + /// /// This test tries to validate a runtime config file that is not compliant with the runtime config JSON schema. /// It validates no additional properties are defined in the config file.