notex.nvim/tests/unit/utils/test_validation.lua

282 lines
8.6 KiB
Lua
Raw Normal View History

2025-10-05 20:16:33 -04:00
-- 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 = '<script>alert("xss")</script>'
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<name>.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)