test: add data validation tests
This commit is contained in:
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user