From f9a421fd1558837bb2d62de812afc8400eadfbcf Mon Sep 17 00:00:00 2001 From: Richard Ward Date: Tue, 30 Dec 2025 12:58:42 +0000 Subject: [PATCH] config: packages,form,builder (5 files) --- fakemui/icons/SkipNext.tsx | 9 ++ fakemui/icons/SkipPrevious.tsx | 9 ++ packages/form_builder/seed/metadata.json | 6 +- .../seed/scripts/tests/validate.cases.json | 61 ++++++++++ .../seed/scripts/tests/validate.test.lua | 105 ++++++++++++++++++ 5 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 fakemui/icons/SkipNext.tsx create mode 100644 fakemui/icons/SkipPrevious.tsx create mode 100644 packages/form_builder/seed/scripts/tests/validate.cases.json create mode 100644 packages/form_builder/seed/scripts/tests/validate.test.lua diff --git a/fakemui/icons/SkipNext.tsx b/fakemui/icons/SkipNext.tsx new file mode 100644 index 000000000..2d9650234 --- /dev/null +++ b/fakemui/icons/SkipNext.tsx @@ -0,0 +1,9 @@ +import React from 'react' +import { Icon, IconProps } from './Icon' + +export const SkipNext = (props: IconProps) => ( + + + + +) diff --git a/fakemui/icons/SkipPrevious.tsx b/fakemui/icons/SkipPrevious.tsx new file mode 100644 index 000000000..1118f9a7c --- /dev/null +++ b/fakemui/icons/SkipPrevious.tsx @@ -0,0 +1,9 @@ +import React from 'react' +import { Icon, IconProps } from './Icon' + +export const SkipPrevious = (props: IconProps) => ( + + + + +) diff --git a/packages/form_builder/seed/metadata.json b/packages/form_builder/seed/metadata.json index d40848457..83f5dc8c2 100644 --- a/packages/form_builder/seed/metadata.json +++ b/packages/form_builder/seed/metadata.json @@ -26,11 +26,13 @@ "tests": { "scripts": [ "tests/metadata.test.lua", - "tests/components.test.lua" + "tests/components.test.lua", + "tests/validate.test.lua" ], "cases": [ "tests/metadata.cases.json", - "tests/components.cases.json" + "tests/components.cases.json", + "tests/validate.cases.json" ] }, "minLevel": 1 diff --git a/packages/form_builder/seed/scripts/tests/validate.cases.json b/packages/form_builder/seed/scripts/tests/validate.cases.json new file mode 100644 index 000000000..053df0b5d --- /dev/null +++ b/packages/form_builder/seed/scripts/tests/validate.cases.json @@ -0,0 +1,61 @@ +{ + "required": { + "customMessage": [ + { "message": "Please fill this in" }, + { "message": "Required field" }, + { "message": "Cannot be empty" } + ] + }, + "email": { + "validPatterns": [ + { "email": "test@example.com" }, + { "email": "user.name@domain.org" }, + { "email": "admin@sub.domain.co.uk" }, + { "email": "a@b.c" } + ], + "invalidPatterns": [ + { "email": "invalid" }, + { "email": "@nodomain.com" }, + { "email": "noat.com" }, + { "email": "spaces in@email.com" } + ], + "customMessage": [ + { "message": "Enter valid email address" }, + { "message": "Email format invalid" } + ] + }, + "minLength": { + "rules": [ + { "length": 1 }, + { "length": 8 }, + { "length": 16 }, + { "length": 100 } + ], + "customMessage": [ + { "length": 8, "message": "Password must be 8+ characters" }, + { "length": 3, "message": "Username too short" } + ] + }, + "maxLength": { + "rules": [ + { "length": 50 }, + { "length": 100 }, + { "length": 255 }, + { "length": 1000 } + ] + }, + "pattern": { + "rules": [ + { "name": "phone", "regex": "^%d%d%d%-%d%d%d%-%d%d%d%d$", "message": "Invalid phone" }, + { "name": "alphanumeric", "regex": "^%w+$", "message": "Letters and numbers only" }, + { "name": "zip", "regex": "^%d%d%d%d%d$", "message": "Invalid ZIP code" } + ], + "matchTests": [ + { "regex": "^%d+$", "value": "12345", "expected": true }, + { "regex": "^%d+$", "value": "abc", "expected": false }, + { "regex": "^%w+$", "value": "test123", "expected": true }, + { "regex": "^%w+$", "value": "test 123", "expected": false }, + { "regex": "^%a+$", "value": "onlyletters", "expected": true } + ] + } +} diff --git a/packages/form_builder/seed/scripts/tests/validate.test.lua b/packages/form_builder/seed/scripts/tests/validate.test.lua new file mode 100644 index 000000000..d7418041d --- /dev/null +++ b/packages/form_builder/seed/scripts/tests/validate.test.lua @@ -0,0 +1,105 @@ +-- Validation Tests +-- Parameterized tests for form validation rules + +local describe = require("lua_test.describe") +local it = require("lua_test.it") +local it_each = require("lua_test.it_each") +local expect = require("lua_test.expect") + +local cases = require("tests.validate.cases") +local required = require("validate.required") +local email = require("validate.email") +local min_length = require("validate.min_length") +local max_length = require("validate.max_length") +local pattern = require("validate.pattern") + +describe("form validation", function() + + describe("required", function() + it("should create required rule with default message", function() + local rule = required() + expect(rule.type).toBe("required") + expect(rule.message).toBe("This field is required") + end) + + it_each(cases.required.customMessage, "should use custom message: '$message'", function(case) + local rule = required(case.message) + expect(rule.message).toBe(case.message) + end) + end) + + describe("email", function() + it("should create email rule with pattern", function() + local rule = email() + expect(rule.type).toBe("email") + expect(rule.pattern).toBeTruthy() + end) + + it_each(cases.email.validPatterns, "pattern should match '$email'", function(case) + local rule = email() + local matches = string.match(case.email, rule.pattern) + expect(matches).toBeTruthy() + end) + + it_each(cases.email.invalidPatterns, "pattern should reject '$email'", function(case) + local rule = email() + local matches = string.match(case.email, rule.pattern) + expect(matches).toBe(nil) + end) + + it_each(cases.email.customMessage, "should use custom message: '$message'", function(case) + local rule = email(case.message) + expect(rule.message).toBe(case.message) + end) + end) + + describe("min_length", function() + it_each(cases.minLength.rules, "should create rule for min $length chars", function(case) + local rule = min_length(case.length) + expect(rule.type).toBe("minLength") + expect(rule.value).toBe(case.length) + end) + + it("should generate default message with length", function() + local rule = min_length(8) + expect(rule.message).toContain("8") + end) + + it_each(cases.minLength.customMessage, "should use custom message", function(case) + local rule = min_length(case.length, case.message) + expect(rule.message).toBe(case.message) + end) + end) + + describe("max_length", function() + it_each(cases.maxLength.rules, "should create rule for max $length chars", function(case) + local rule = max_length(case.length) + expect(rule.type).toBe("maxLength") + expect(rule.value).toBe(case.length) + end) + + it("should generate default message with length", function() + local rule = max_length(100) + expect(rule.message).toContain("100") + end) + end) + + describe("pattern", function() + it_each(cases.pattern.rules, "should create rule with pattern: $name", function(case) + local rule = pattern(case.regex, case.message) + expect(rule.type).toBe("pattern") + expect(rule.pattern).toBe(case.regex) + end) + + it_each(cases.pattern.matchTests, "pattern '$regex' should match '$value'", function(case) + local matches = string.match(case.value, case.regex) + expect(matches ~= nil).toBe(case.expected) + end) + end) + +end) + +return { + name = "validate.test", + description = "Tests for form validation rules" +}