-- Unit tests for validation utilities local validation = require('notex.utils.validation') describe("validation utilities", function() describe("validate_value", function() it("should validate string values", function() local schema = {type = "string", required = true} local valid, error = validation.validate_value("hello", schema) assert.is_true(valid) assert.equals("Validation passed", error) end) it("should reject required string when nil", function() local schema = {type = "string", required = true} local valid, error = validation.validate_value(nil, schema) assert.is_false(valid) assert.equals("Value is required", error) end) it("should validate string length constraints", function() local schema = {type = "string", min_length = 5, max_length = 10} -- Too short local valid, error = validation.validate_value("hi", schema) assert.is_false(valid) assert.matches("too short", error) -- Too long valid, error = validation.validate_value("this is too long", schema) assert.is_false(valid) assert.matches("too long", error) -- Just right valid, error = validation.validate_value("perfect", schema) assert.is_true(valid) end) it("should validate number values", function() local schema = {type = "number", min_value = 1, max_value = 10} -- Valid number local valid, error = validation.validate_value(5, schema) assert.is_true(valid) -- Too small valid, error = validation.validate_value(0, schema) assert.is_false(valid) assert.matches("too small", error) -- Too large valid, error = validation.validate_value(11, schema) assert.is_false(valid) assert.matches("too large", error) end) it("should validate boolean values", function() local schema = {type = "boolean"} -- Valid booleans local valid, error = validation.validate_value(true, schema) assert.is_true(valid) valid, error = validation.validate_value(false, schema) assert.is_true(valid) -- String conversion valid, error = validation.validate_value("true", schema) assert.is_true(valid) valid, error = validation.validate_value("false", schema) assert.is_true(valid) end) it("should validate array values", function() local schema = {type = "array", min_items = 2, max_items = 5} -- Valid array local valid, error = validation.validate_value({1, 2, 3}, schema) assert.is_true(valid) -- Too few items valid, error = validation.validate_value({1}, schema) assert.is_false(valid) assert.matches("too short", error) -- Too many items valid, error = validation.validate_value({1, 2, 3, 4, 5, 6}, schema) assert.is_false(valid) assert.matches("too long", error) end) it("should validate object values", function() local schema = { type = "object", required_fields = {"name"}, field_types = { name = {type = "string"}, age = {type = "number"} } } -- Valid object local valid, error = validation.validate_value({name = "John", age = 30}, schema) assert.is_true(valid) -- Missing required field valid, error = validation.validate_value({age = 30}, schema) assert.is_false(valid) assert.matches("Missing required field", error) -- Invalid field type valid, error = validation.validate_value({name = 123, age = 30}, schema) assert.is_false(valid) assert.matches("Field 'name' invalid", error) end) end) describe("validate_document_properties", function() it("should validate document properties against schema", function() local schema_definition = { title = {type = "string", required = true}, status = {type = "string", enum = {"draft", "published"}}, priority = {type = "number", min_value = 1, max_value = 5} } local properties = { title = "Test Document", status = "draft", priority = 3 } local valid, result = validation.validate_document_properties(properties, schema_definition) assert.is_true(valid) assert.equals(0, #result.errors) end) it("should return errors for invalid properties", function() local schema_definition = { title = {type = "string", required = true}, status = {type = "string", enum = {"draft", "published"}} } local properties = { status = "invalid_status" -- Missing required title, invalid status } local valid, result = validation.validate_document_properties(properties, schema_definition) assert.is_false(valid) assert.is_true(#result.errors > 0) end) it("should include warnings for unknown properties", function() local schema_definition = { title = {type = "string", required = true} } local properties = { title = "Test Document", unknown_property = "value" } local valid, result = validation.validate_document_properties(properties, schema_definition) assert.is_true(valid) assert.is_true(#result.warnings > 0) end) end) describe("validate_query_params", function() it("should validate query parameters", function() local allowed_params = { limit = {type = "number", min_value = 1, max_value = 100}, sort = {type = "string", enum = {"asc", "desc"}}, filter = {type = "string", required = false} } local params = { limit = 10, sort = "asc" } local valid, errors = validation.validate_query_params(params, allowed_params) assert.is_true(valid) assert.equals(0, #errors) end) it("should reject unknown parameters", function() local allowed_params = { limit = {type = "number"} } local params = { limit = 10, unknown = "value" } local valid, errors = validation.validate_query_params(params, allowed_params) assert.is_false(valid) assert.is_true(#errors > 0) end) end) describe("sanitize_input", function() it("should remove dangerous characters", function() local input = '' local sanitized = validation.sanitize_input(input) assert.equals('scriptalertxss/script', sanitized) end) it("should limit length", function() local input = string.rep("a", 100) local sanitized = validation.sanitize_input(input, {max_length = 10}) assert.equals(10, #sanitized) end) it("should trim whitespace", function() local input = " hello world " local sanitized = validation.sanitize_input(input) assert.equals("hello world", sanitized) end) end) describe("validate_file_path", function() it("should validate safe file paths", function() local valid, error = validation.validate_file_path("/home/user/document.md") assert.is_true(valid) end) it("should reject paths with invalid characters", function() local valid, error = validation.validate_file_path('file.md') assert.is_false(valid) assert.matches("Invalid characters", error) end) it("should reject directory traversal", function() local valid, error = validation.validate_file_path("../../../etc/passwd") assert.is_false(valid) assert.matches("Directory traversal", error) end) it("should reject empty paths", function() local valid, error = validation.validate_file_path("") assert.is_false(valid) assert.equals("Empty file path", error) end) end) describe("create_schema", function() it("should create validation schema", function() local schema = validation.create_schema("test_field", { type = "string", required = true, min_length = 5 }) assert.equals("test_field", schema.field_name) assert.equals("string", schema.type) assert.is_true(schema.required) assert.equals(5, schema.min_length) end) end) describe("create_validation_summary", function() it("should create validation summary", function() local results = { {valid = true}, {valid = false, errors = {"Error 1"}}, {valid = false, errors = {"Error 2", "Error 3"}, warnings = {"Warning 1"}}, {valid = true, warnings = {"Warning 2"}} } local summary = validation.create_validation_summary(results) assert.equals(4, summary.total) assert.equals(2, summary.valid) assert.equals(2, summary.invalid) assert.equals(3, #summary.errors) assert.equals(2, #summary.warnings) end) end) end)