/** * 字段验证规则测试 */ import { parseValidationRules, serializeValidationRules, validateFieldValue, validateValidationRules, getSupportedValidations, ValidationRule, } from '../field-validation' describe('field-validation', () => { describe('parseValidationRules', () => { it('should return null for empty string', () => { expect(parseValidationRules('')).toBeNull() expect(parseValidationRules(' ')).toBeNull() }) it('should return null for null/undefined', () => { expect(parseValidationRules(null)).toBeNull() expect(parseValidationRules(undefined)).toBeNull() }) it('should parse valid JSON', () => { const rules = parseValidationRules('{"required":true,"maxLength":100}') expect(rules).toEqual({ required: true, maxLength: 100 }) }) it('should return null for invalid JSON', () => { expect(parseValidationRules('invalid json')).toBeNull() expect(parseValidationRules('{broken')).toBeNull() }) it('should return null for non-object JSON', () => { expect(parseValidationRules('"string"')).toBeNull() expect(parseValidationRules('123')).toBeNull() expect(parseValidationRules('null')).toBeNull() }) }) describe('serializeValidationRules', () => { it('should return empty string for null', () => { expect(serializeValidationRules(null)).toBe('') }) it('should return empty string for empty rules', () => { expect(serializeValidationRules({})).toBe('') expect(serializeValidationRules({ required: false })).toBe('') }) it('should serialize required rule', () => { const result = serializeValidationRules({ required: true }) expect(JSON.parse(result)).toEqual({ required: true }) }) it('should serialize length rules', () => { const result = serializeValidationRules({ minLength: 5, maxLength: 100 }) expect(JSON.parse(result)).toEqual({ minLength: 5, maxLength: 100 }) }) it('should serialize number range rules', () => { const result = serializeValidationRules({ min: 0, max: 100 }) expect(JSON.parse(result)).toEqual({ min: 0, max: 100 }) }) it('should serialize pattern rule', () => { const result = serializeValidationRules({ pattern: '^[A-Z]+$' }) expect(JSON.parse(result)).toEqual({ pattern: '^[A-Z]+$' }) }) it('should include custom messages', () => { const result = serializeValidationRules({ required: true, requiredMessage: '请填写此字段', }) expect(JSON.parse(result)).toEqual({ required: true, requiredMessage: '请填写此字段', }) }) it('should filter out zero/undefined values for length', () => { const result = serializeValidationRules({ minLength: 0, maxLength: undefined }) expect(result).toBe('') }) }) describe('validateFieldValue', () => { describe('required validation', () => { const rules: ValidationRule = { required: true } it('should fail for empty value', () => { const result = validateFieldValue('', 'text', rules, '字段') expect(result.valid).toBe(false) expect(result.errors).toContain('字段不能为空') }) it('should fail for whitespace only', () => { const result = validateFieldValue(' ', 'text', rules, '字段') expect(result.valid).toBe(false) }) it('should pass for non-empty value', () => { const result = validateFieldValue('hello', 'text', rules, '字段') expect(result.valid).toBe(true) expect(result.errors).toHaveLength(0) }) it('should use custom message', () => { const rulesWithMessage: ValidationRule = { required: true, requiredMessage: '请输入商品型号', } const result = validateFieldValue('', 'text', rulesWithMessage) expect(result.errors).toContain('请输入商品型号') }) }) describe('length validation', () => { it('should fail for value shorter than minLength', () => { const rules: ValidationRule = { minLength: 5 } const result = validateFieldValue('abc', 'text', rules, '字段') expect(result.valid).toBe(false) expect(result.errors[0]).toContain('不能少于5个字符') }) it('should fail for value longer than maxLength', () => { const rules: ValidationRule = { maxLength: 5 } const result = validateFieldValue('abcdefgh', 'text', rules, '字段') expect(result.valid).toBe(false) expect(result.errors[0]).toContain('不能超过5个字符') }) it('should pass for value within range', () => { const rules: ValidationRule = { minLength: 2, maxLength: 10 } const result = validateFieldValue('hello', 'text', rules) expect(result.valid).toBe(true) }) it('should skip validation for empty non-required field', () => { const rules: ValidationRule = { minLength: 5 } const result = validateFieldValue('', 'text', rules) expect(result.valid).toBe(true) }) }) describe('number range validation', () => { it('should fail for value below min', () => { const rules: ValidationRule = { min: 10 } const result = validateFieldValue('5', 'number', rules, '数量') expect(result.valid).toBe(false) expect(result.errors[0]).toContain('不能小于10') }) it('should fail for value above max', () => { const rules: ValidationRule = { max: 100 } const result = validateFieldValue('150', 'number', rules, '数量') expect(result.valid).toBe(false) expect(result.errors[0]).toContain('不能大于100') }) it('should pass for value within range', () => { const rules: ValidationRule = { min: 0, max: 100 } const result = validateFieldValue('50', 'number', rules) expect(result.valid).toBe(true) }) it('should fail for non-numeric value', () => { const rules: ValidationRule = { min: 0 } const result = validateFieldValue('abc', 'number', rules, '数量') expect(result.valid).toBe(false) expect(result.errors[0]).toContain('必须是有效的数字') }) it('should handle zero as valid min', () => { const rules: ValidationRule = { min: 0 } const result = validateFieldValue('0', 'number', rules) expect(result.valid).toBe(true) }) it('should handle negative numbers', () => { const rules: ValidationRule = { min: -10, max: 10 } const result = validateFieldValue('-5', 'number', rules) expect(result.valid).toBe(true) }) }) describe('pattern validation', () => { it('should fail for value not matching pattern', () => { const rules: ValidationRule = { pattern: '^[A-Z]{2}\\d{4}$' } const result = validateFieldValue('abc123', 'text', rules, '编码') expect(result.valid).toBe(false) expect(result.errors[0]).toContain('格式不正确') }) it('should pass for value matching pattern', () => { const rules: ValidationRule = { pattern: '^[A-Z]{2}\\d{4}$' } const result = validateFieldValue('AB1234', 'text', rules) expect(result.valid).toBe(true) }) it('should use custom pattern message', () => { const rules: ValidationRule = { pattern: '^[A-Z]+$', patternMessage: '只能输入大写字母', } const result = validateFieldValue('abc', 'text', rules) expect(result.errors).toContain('只能输入大写字母') }) it('should handle invalid regex gracefully', () => { const rules: ValidationRule = { pattern: '[invalid(' } const result = validateFieldValue('test', 'text', rules) // Should not throw, just skip validation expect(result.valid).toBe(true) }) }) describe('combined validations', () => { it('should collect all errors', () => { const rules: ValidationRule = { required: true, minLength: 10, pattern: '^[A-Z]+$', } const result = validateFieldValue('abc', 'text', rules, '字段') expect(result.valid).toBe(false) expect(result.errors.length).toBeGreaterThanOrEqual(2) }) it('should stop at required if empty', () => { const rules: ValidationRule = { required: true, minLength: 10, } const result = validateFieldValue('', 'text', rules) expect(result.errors).toHaveLength(1) }) }) describe('null rules', () => { it('should pass with null rules', () => { const result = validateFieldValue('anything', 'text', null) expect(result.valid).toBe(true) }) }) }) describe('validateValidationRules', () => { it('should pass for valid rules', () => { const result = validateValidationRules({ required: true, minLength: 5, maxLength: 100, }) expect(result.valid).toBe(true) }) it('should fail when minLength > maxLength', () => { const result = validateValidationRules({ minLength: 100, maxLength: 5, }) expect(result.valid).toBe(false) expect(result.error).toContain('最小长度不能大于最大长度') }) it('should fail when min > max', () => { const result = validateValidationRules({ min: 100, max: 5, }) expect(result.valid).toBe(false) expect(result.error).toContain('最小值不能大于最大值') }) it('should fail for invalid regex', () => { const result = validateValidationRules({ pattern: '[invalid(', }) expect(result.valid).toBe(false) expect(result.error).toContain('正则表达式格式无效') }) it('should pass for valid regex', () => { const result = validateValidationRules({ pattern: '^[A-Z]+$', }) expect(result.valid).toBe(true) }) }) describe('getSupportedValidations', () => { it('should return correct validations for text', () => { const supported = getSupportedValidations('text') expect(supported).toContain('required') expect(supported).toContain('minLength') expect(supported).toContain('maxLength') expect(supported).toContain('pattern') expect(supported).not.toContain('min') expect(supported).not.toContain('max') }) it('should return correct validations for number', () => { const supported = getSupportedValidations('number') expect(supported).toContain('required') expect(supported).toContain('min') expect(supported).toContain('max') expect(supported).not.toContain('minLength') expect(supported).not.toContain('pattern') }) it('should return only required for select', () => { const supported = getSupportedValidations('select') expect(supported).toContain('required') expect(supported).toHaveLength(1) }) it('should return only required for checkbox', () => { const supported = getSupportedValidations('checkbox') expect(supported).toContain('required') expect(supported).toHaveLength(1) }) it('should return common validations for unknown type', () => { const supported = getSupportedValidations('unknown') expect(supported).toContain('required') }) }) })