test: add data validation tests

This commit is contained in:
张翔
2026-03-10 11:49:51 +08:00
parent 24cec5f572
commit 7e885c88a7
2 changed files with 355 additions and 0 deletions
+275
View File
@@ -0,0 +1,275 @@
import { describe, it, expect } from '@jest/globals';
import {
validateEmail,
validatePhone,
validatePassword,
validateUrl,
validateRequired,
validateLength,
validateRange,
validateChineseId,
validateUsername,
} from './validation';
describe('validation', () => {
describe('email validation', () => {
it('should accept valid email', () => {
expect(validateEmail('test@example.com')).toBe(true);
expect(validateEmail('user.name@example.com')).toBe(true);
expect(validateEmail('user+tag@example.co.uk')).toBe(true);
});
it('should reject invalid email', () => {
expect(validateEmail('invalid')).toBe(false);
expect(validateEmail('invalid@')).toBe(false);
expect(validateEmail('@example.com')).toBe(false);
expect(validateEmail('test@')).toBe(false);
expect(validateEmail('')).toBe(false);
});
it('should reject null or undefined', () => {
expect(validateEmail(null as any)).toBe(false);
expect(validateEmail(undefined as any)).toBe(false);
});
it('should reject non-string values', () => {
expect(validateEmail(123 as any)).toBe(false);
expect(validateEmail({} as any)).toBe(false);
expect(validateEmail([] as any)).toBe(false);
});
});
describe('phone validation', () => {
it('should accept valid phone numbers', () => {
expect(validatePhone('13800138000')).toBe(true);
expect(validatePhone('15912345678')).toBe(true);
expect(validatePhone('18600001111')).toBe(true);
});
it('should reject invalid phone numbers', () => {
expect(validatePhone('123')).toBe(false);
expect(validatePhone('12345678901')).toBe(false);
expect(validatePhone('10800138000')).toBe(false);
expect(validatePhone('1380013800')).toBe(false);
expect(validatePhone('')).toBe(false);
});
it('should reject null or undefined', () => {
expect(validatePhone(null as any)).toBe(false);
expect(validatePhone(undefined as any)).toBe(false);
});
it('should reject non-string values', () => {
expect(validatePhone(13800138000 as any)).toBe(false);
expect(validatePhone({} as any)).toBe(false);
});
});
describe('password validation', () => {
it('should accept valid passwords', () => {
expect(validatePassword('password123')).toBe(true);
expect(validatePassword('12345678')).toBe(true);
expect(validatePassword('abcdefgh')).toBe(true);
});
it('should reject short passwords', () => {
expect(validatePassword('pass')).toBe(false);
expect(validatePassword('1234567')).toBe(false);
expect(validatePassword('')).toBe(false);
});
it('should reject null or undefined', () => {
expect(validatePassword(null as any)).toBe(false);
expect(validatePassword(undefined as any)).toBe(false);
});
it('should reject non-string values', () => {
expect(validatePassword(12345678 as any)).toBe(false);
expect(validatePassword({} as any)).toBe(false);
});
});
describe('URL validation', () => {
it('should accept valid URLs', () => {
expect(validateUrl('https://example.com')).toBe(true);
expect(validateUrl('http://example.com')).toBe(true);
expect(validateUrl('https://example.com/path')).toBe(true);
expect(validateUrl('https://example.com?query=1')).toBe(true);
expect(validateUrl('https://example.com#fragment')).toBe(true);
});
it('should reject invalid URLs', () => {
expect(validateUrl('not-a-url')).toBe(false);
expect(validateUrl('')).toBe(false);
expect(validateUrl('example.com')).toBe(false);
});
it('should reject null or undefined', () => {
expect(validateUrl(null as any)).toBe(false);
expect(validateUrl(undefined as any)).toBe(false);
});
it('should reject non-string values', () => {
expect(validateUrl({} as any)).toBe(false);
expect(validateUrl([] as any)).toBe(false);
});
});
describe('required validation', () => {
it('should accept non-empty strings', () => {
expect(validateRequired('test')).toBe(true);
expect(validateRequired(' test ')).toBe(true);
});
it('should reject empty strings', () => {
expect(validateRequired('')).toBe(false);
expect(validateRequired(' ')).toBe(false);
});
it('should accept valid numbers', () => {
expect(validateRequired(123)).toBe(true);
expect(validateRequired(0)).toBe(true);
expect(validateRequired(-1)).toBe(true);
});
it('should reject NaN', () => {
expect(validateRequired(NaN)).toBe(false);
});
it('should accept non-empty arrays', () => {
expect(validateRequired([1, 2, 3])).toBe(true);
expect(validateRequired(['a'])).toBe(true);
});
it('should reject empty arrays', () => {
expect(validateRequired([])).toBe(false);
});
it('should accept objects', () => {
expect(validateRequired({})).toBe(true);
expect(validateRequired({ a: 1 })).toBe(true);
});
it('should reject null and undefined', () => {
expect(validateRequired(null)).toBe(false);
expect(validateRequired(undefined)).toBe(false);
});
it('should accept booleans', () => {
expect(validateRequired(true)).toBe(true);
expect(validateRequired(false)).toBe(true);
});
});
describe('length validation', () => {
it('should accept strings within range', () => {
expect(validateLength('test', 3, 5)).toBe(true);
expect(validateLength('hello', 3, 10)).toBe(true);
});
it('should reject strings shorter than minimum', () => {
expect(validateLength('ab', 3, 10)).toBe(false);
expect(validateLength('', 1, 10)).toBe(false);
});
it('should reject strings longer than maximum', () => {
expect(validateLength('hello world', 3, 5)).toBe(false);
expect(validateLength('a'.repeat(20), 1, 10)).toBe(false);
});
it('should reject non-string values', () => {
expect(validateLength(123 as any, 1, 10)).toBe(false);
expect(validateLength(null as any, 1, 10)).toBe(false);
});
});
describe('range validation', () => {
it('should accept numbers within range', () => {
expect(validateRange(5, 1, 10)).toBe(true);
expect(validateRange(1, 1, 10)).toBe(true);
expect(validateRange(10, 1, 10)).toBe(true);
});
it('should reject numbers below minimum', () => {
expect(validateRange(0, 1, 10)).toBe(false);
expect(validateRange(-5, 0, 10)).toBe(false);
});
it('should reject numbers above maximum', () => {
expect(validateRange(11, 1, 10)).toBe(false);
expect(validateRange(100, 1, 10)).toBe(false);
});
it('should reject NaN', () => {
expect(validateRange(NaN, 1, 10)).toBe(false);
});
it('should reject non-number values', () => {
expect(validateRange('5' as any, 1, 10)).toBe(false);
expect(validateRange(null as any, 1, 10)).toBe(false);
});
});
describe('Chinese ID validation', () => {
it('should accept valid Chinese ID numbers', () => {
expect(validateChineseId('11010519900307888X')).toBe(true);
expect(validateChineseId('110105199003078888')).toBe(true);
expect(validateChineseId('110105200001011234')).toBe(true);
});
it('should reject invalid Chinese ID numbers', () => {
expect(validateChineseId('123456789012345678')).toBe(false);
expect(validateChineseId('11010519900307888')).toBe(false);
expect(validateChineseId('11010519900307888XX')).toBe(false);
expect(validateChineseId('')).toBe(false);
});
it('should reject null or undefined', () => {
expect(validateChineseId(null as any)).toBe(false);
expect(validateChineseId(undefined as any)).toBe(false);
});
it('should reject non-string values', () => {
expect(validateChineseId(123456789012345678 as any)).toBe(false);
expect(validateChineseId({} as any)).toBe(false);
});
});
describe('username validation', () => {
it('should accept valid usernames', () => {
expect(validateUsername('user123')).toBe(true);
expect(validateUsername('test_user')).toBe(true);
expect(validateUsername('User123')).toBe(true);
expect(validateUsername('a1')).toBe(false);
expect(validateUsername('a')).toBe(false);
});
it('should reject usernames with special characters', () => {
expect(validateUsername('user@123')).toBe(false);
expect(validateUsername('user-name')).toBe(false);
expect(validateUsername('user.name')).toBe(false);
expect(validateUsername('user name')).toBe(false);
});
it('should reject usernames that are too short', () => {
expect(validateUsername('ab')).toBe(false);
expect(validateUsername('a')).toBe(false);
expect(validateUsername('')).toBe(false);
});
it('should reject usernames that are too long', () => {
expect(validateUsername('a'.repeat(21))).toBe(false);
expect(validateUsername('user123456789012345678')).toBe(false);
});
it('should reject null or undefined', () => {
expect(validateUsername(null as any)).toBe(false);
expect(validateUsername(undefined as any)).toBe(false);
});
it('should reject non-string values', () => {
expect(validateUsername(123 as any)).toBe(false);
expect(validateUsername({} as any)).toBe(false);
});
});
});
+80
View File
@@ -0,0 +1,80 @@
export function validateEmail(email: string): boolean {
if (!email || typeof email !== 'string') {
return false;
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
export function validatePhone(phone: string): boolean {
if (!phone || typeof phone !== 'string') {
return false;
}
const phoneRegex = /^1[3-9]\d{9}$/;
return phoneRegex.test(phone);
}
export function validatePassword(password: string): boolean {
if (!password || typeof password !== 'string') {
return false;
}
return password.length >= 8;
}
export function validateUrl(url: string): boolean {
if (!url || typeof url !== 'string') {
return false;
}
try {
new URL(url);
return true;
} catch {
return false;
}
}
export function validateRequired(value: unknown): boolean {
if (value === null || value === undefined) {
return false;
}
if (typeof value === 'string') {
return value.trim().length > 0;
}
if (typeof value === 'number') {
return !isNaN(value);
}
if (Array.isArray(value)) {
return value.length > 0;
}
return true;
}
export function validateLength(value: string, min: number, max: number): boolean {
if (typeof value !== 'string') {
return false;
}
return value.length >= min && value.length <= max;
}
export function validateRange(value: number, min: number, max: number): boolean {
if (typeof value !== 'number' || isNaN(value)) {
return false;
}
return value >= min && value <= max;
}
export function validateChineseId(id: string): boolean {
if (!id || typeof id !== 'string') {
return false;
}
const idRegex = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
return idRegex.test(id);
}
export function validateUsername(username: string): boolean {
if (!username || typeof username !== 'string') {
return false;
}
const usernameRegex = /^[a-zA-Z0-9_]{3,20}$/;
return usernameRegex.test(username);
}