feat: 建立完整的测试数据管理体系

- 创建测试数据文件test-data.ts,包含所有测试场景数据
- 增强TestDataGenerator,添加边界、安全、性能等测试数据生成方法
- 支持XSS、SQL注入、路径遍历等安全测试
- 支持WCAG可访问性测试数据
- 支持Core Web Vitals性能测试数据
- 支持响应式断点测试数据
This commit is contained in:
张翔
2026-02-28 15:04:45 +08:00
parent 18881b8807
commit 5cdb021994
2 changed files with 422 additions and 0 deletions
+216
View File
@@ -0,0 +1,216 @@
export const VALID_CONTACT_DATA = {
name: '张三',
email: 'zhangsan@example.com',
phone: '13800138000',
subject: '产品咨询',
message: '您好,我对贵公司的产品很感兴趣,希望能了解更多信息。',
};
export const INVALID_EMAIL_CASES = [
{ email: 'invalid-email', description: '无@符号' },
{ email: '@example.com', description: '无用户名' },
{ email: 'user@', description: '无域名' },
{ email: 'user@domain', description: '无顶级域名' },
{ email: 'user domain.com', description: '包含空格' },
{ email: 'user@domain..com', description: '连续点号' },
];
export const INVALID_PHONE_CASES = [
{ phone: '123', description: '过短' },
{ phone: '123456789012345', description: '过长' },
{ phone: 'abcdefghijk', description: '纯字母' },
{ phone: '123-456-7890', description: '包含连字符' },
{ phone: '138 0013 8000', description: '包含空格' },
];
export const SPECIAL_CHARACTER_CASES = [
{ name: '!@#$%^&*()', description: '特殊符号' },
{ name: '<script>alert("XSS")</script>', description: 'XSS脚本' },
{ name: "'; DROP TABLE users; --", description: 'SQL注入' },
{ name: '../../../etc/passwd', description: '路径遍历' },
{ name: '{{template}}', description: '模板注入' },
];
export const LONG_CONTENT_CASES = [
{ message: 'A'.repeat(500), description: '500字符消息' },
{ message: 'A'.repeat(1000), description: '1000字符消息' },
{ message: 'A'.repeat(1001), description: '超长消息' },
];
export const BOUNDARY_CASES = {
name: {
minLength: '张',
maxLength: '张三李四王五赵六钱七孙八周九吴十',
empty: '',
whitespace: ' ',
},
phone: {
minLength: '1380013800',
maxLength: '138001380001',
validFormat: '13800138000',
},
email: {
minLength: 'a@b.c',
maxLength: `${'a'.repeat(64)}@${'b'.repeat(63)}.com`,
},
};
export const PERFORMANCE_THRESHOLDS = {
loadTime: 5000,
firstContentfulPaint: 1800,
largestContentfulPaint: 2500,
timeToInteractive: 3800,
cumulativeLayoutShift: 0.1,
firstInputDelay: 100,
};
export const RESPONSIVE_BREAKPOINTS = [
{ name: 'mobile-small', width: 320, height: 568 },
{ name: 'mobile-medium', width: 375, height: 667 },
{ name: 'mobile-large', width: 414, height: 896 },
{ name: 'tablet-small', width: 768, height: 1024 },
{ name: 'tablet-large', width: 1024, height: 768 },
{ name: 'desktop-small', width: 1280, height: 720 },
{ name: 'desktop-medium', width: 1366, height: 768 },
{ name: 'desktop-large', width: 1920, height: 1080 },
];
export const NAVIGATION_ITEMS = [
{ label: '首页', href: '#home', expectedUrl: '/' },
{ label: '关于我们', href: '#about', expectedUrl: '/' },
{ label: '服务', href: '#services', expectedUrl: '/' },
{ label: '产品', href: '#products', expectedUrl: '/' },
{ label: '案例', href: '#cases', expectedUrl: '/' },
{ label: '新闻', href: '#news', expectedUrl: '/' },
{ label: '联系我们', href: '#contact', expectedUrl: '/' },
];
export const COMPANY_INFO = {
name: '四川睿新致远科技有限公司',
address: '四川省成都市高新区天府大道中段1268号天府软件园E区1栋',
phone: '028-88888888',
email: 'contact@ruixin.com',
workHours: [
{ day: '周一至周五', hours: '9:00 - 18:00' },
{ day: '周六', hours: '9:00 - 12:00' },
{ day: '周日', hours: '休息' },
],
};
export const SERVICES = [
{
id: 'service-1',
title: '企业数字化转型',
description: '帮助企业实现数字化升级',
},
{
id: 'service-2',
title: '智能制造解决方案',
description: '提供智能化生产线解决方案',
},
{
id: 'service-3',
title: '数据分析服务',
description: '专业的数据分析与可视化服务',
},
];
export const PRODUCTS = [
{
id: 'product-1',
title: '智能生产管理系统',
description: '一体化生产管理平台',
},
{
id: 'product-2',
title: '数据分析平台',
description: '企业级数据分析工具',
},
{
id: 'product-3',
title: '物联网监控平台',
description: '实时设备监控与管理',
},
];
export const NEWS_ITEMS = [
{
id: 'news-1',
title: '公司获得ISO9001认证',
date: '2024-01-15',
summary: '公司成功通过ISO9001质量管理体系认证',
},
{
id: 'news-2',
title: '新产品发布会圆满成功',
date: '2024-02-20',
summary: '智能生产管理系统2.0版本正式发布',
},
];
export const SECURITY_TEST_CASES = {
xssPayloads: [
'<script>alert("XSS")</script>',
'<img src=x onerror=alert("XSS")>',
'<svg onload=alert("XSS")>',
'javascript:alert("XSS")',
'<body onload=alert("XSS")>',
],
sqlInjectionPayloads: [
"'; DROP TABLE users; --",
"' OR '1'='1",
"' UNION SELECT * FROM users --",
"1; INSERT INTO users VALUES ('hacker')",
],
pathTraversalPayloads: [
'../../../etc/passwd',
'..\\..\\..\\windows\\system32\\config\\sam',
'....//....//....//etc/passwd',
],
};
export const ACCESSIBILITY_TEST_CASES = {
colorContrastRatios: {
normalText: 4.5,
largeText: 3.0,
uiComponents: 3.0,
},
touchTargetSize: 44,
focusIndicatorVisible: true,
keyboardNavigationRequired: true,
};
export const ERROR_MESSAGES = {
requiredField: '此字段为必填项',
invalidEmail: '请输入有效的邮箱地址',
invalidPhone: '请输入有效的手机号码',
messageTooShort: '消息内容至少需要10个字符',
messageTooLong: '消息内容不能超过1000个字符',
submissionFailed: '提交失败,请稍后重试',
};
export const SUCCESS_MESSAGES = {
formSubmitted: '消息已发送',
thankYou: '感谢您的留言,我们会尽快与您联系',
};
export const TEST_USERS = {
admin: {
username: 'admin',
password: 'admin123',
role: 'administrator',
},
user: {
username: 'testuser',
password: 'test123',
role: 'user',
},
};
export const API_ENDPOINTS = {
contactForm: '/api/contact',
newsletter: '/api/newsletter',
services: '/api/services',
products: '/api/products',
news: '/api/news',
};
+206
View File
@@ -251,4 +251,210 @@ export class TestDataGenerator {
## Message
${this.generateMessage()}`;
}
static generateBoundaryTestData(): {
name: { minLength: string; maxLength: string; empty: string; whitespace: string };
phone: { minLength: string; maxLength: string; validFormat: string };
email: { minLength: string; maxLength: string };
} {
return {
name: {
minLength: '张',
maxLength: '张三李四王五赵六钱七孙八周九吴十',
empty: '',
whitespace: ' ',
},
phone: {
minLength: '1380013800',
maxLength: '138001380001',
validFormat: '13800138000',
},
email: {
minLength: 'a@b.c',
maxLength: `${'a'.repeat(64)}@${'b'.repeat(63)}.com`,
},
};
}
static generateSecurityTestData(): {
xssPayloads: string[];
sqlInjectionPayloads: string[];
pathTraversalPayloads: string[];
} {
return {
xssPayloads: [
'<script>alert("XSS")</script>',
'<img src=x onerror=alert("XSS")>',
'<svg onload=alert("XSS")>',
'javascript:alert("XSS")',
'<body onload=alert("XSS")>',
],
sqlInjectionPayloads: [
"'; DROP TABLE users; --",
"' OR '1'='1",
"' UNION SELECT * FROM users --",
"1; INSERT INTO users VALUES ('hacker')",
],
pathTraversalPayloads: [
'../../../etc/passwd',
'..\\..\\..\\windows\\system32\\config\\sam',
'....//....//....//etc/passwd',
],
};
}
static generateAccessibilityTestData(): {
colorContrastRatios: { normalText: number; largeText: number; uiComponents: number };
touchTargetSize: number;
focusIndicatorVisible: boolean;
keyboardNavigationRequired: boolean;
} {
return {
colorContrastRatios: {
normalText: 4.5,
largeText: 3.0,
uiComponents: 3.0,
},
touchTargetSize: 44,
focusIndicatorVisible: true,
keyboardNavigationRequired: true,
};
}
static generatePerformanceTestData(): {
thresholds: {
loadTime: number;
firstContentfulPaint: number;
largestContentfulPaint: number;
timeToInteractive: number;
cumulativeLayoutShift: number;
firstInputDelay: number;
};
budgets: {
totalPageSize: number;
imageSize: number;
scriptSize: number;
stylesheetSize: number;
};
} {
return {
thresholds: {
loadTime: 5000,
firstContentfulPaint: 1800,
largestContentfulPaint: 2500,
timeToInteractive: 3800,
cumulativeLayoutShift: 0.1,
firstInputDelay: 100,
},
budgets: {
totalPageSize: 1600000,
imageSize: 500000,
scriptSize: 300000,
stylesheetSize: 100000,
},
};
}
static generateResponsiveTestData(): Array<{
name: string;
width: number;
height: number;
}> {
return [
{ name: 'mobile-small', width: 320, height: 568 },
{ name: 'mobile-medium', width: 375, height: 667 },
{ name: 'mobile-large', width: 414, height: 896 },
{ name: 'tablet-small', width: 768, height: 1024 },
{ name: 'tablet-large', width: 1024, height: 768 },
{ name: 'desktop-small', width: 1280, height: 720 },
{ name: 'desktop-medium', width: 1366, height: 768 },
{ name: 'desktop-large', width: 1920, height: 1080 },
];
}
static generateNavigationTestData(): Array<{
label: string;
href: string;
expectedUrl: string;
}> {
return [
{ label: '首页', href: '#home', expectedUrl: '/' },
{ label: '关于我们', href: '#about', expectedUrl: '/' },
{ label: '服务', href: '#services', expectedUrl: '/' },
{ label: '产品', href: '#products', expectedUrl: '/' },
{ label: '案例', href: '#cases', expectedUrl: '/' },
{ label: '新闻', href: '#news', expectedUrl: '/' },
{ label: '联系我们', href: '#contact', expectedUrl: '/' },
];
}
static generateCompanyInfoTestData(): {
name: string;
address: string;
phone: string;
email: string;
workHours: Array<{ day: string; hours: string }>;
} {
return {
name: '四川睿新致远科技有限公司',
address: '四川省成都市高新区天府大道中段1268号天府软件园E区1栋',
phone: '028-88888888',
email: 'contact@ruixin.com',
workHours: [
{ day: '周一至周五', hours: '9:00 - 18:00' },
{ day: '周六', hours: '9:00 - 12:00' },
{ day: '周日', hours: '休息' },
],
};
}
static generateErrorTestData(): {
requiredField: string;
invalidEmail: string;
invalidPhone: string;
messageTooShort: string;
messageTooLong: string;
submissionFailed: string;
} {
return {
requiredField: '此字段为必填项',
invalidEmail: '请输入有效的邮箱地址',
invalidPhone: '请输入有效的手机号码',
messageTooShort: '消息内容至少需要10个字符',
messageTooLong: '消息内容不能超过1000个字符',
submissionFailed: '提交失败,请稍后重试',
};
}
static generateSuccessTestData(): {
formSubmitted: string;
thankYou: string;
} {
return {
formSubmitted: '消息已发送',
thankYou: '感谢您的留言,我们会尽快与您联系',
};
}
static generateRandomEmail(): string {
const domains = ['gmail.com', 'outlook.com', 'yahoo.com', 'qq.com', '163.com'];
const username = this.generateAlphanumeric(8);
const domain = domains[Math.floor(Math.random() * domains.length)]!;
return `${username}@${domain}`;
}
static generateRandomChineseName(): string {
const surnames = ['张', '李', '王', '刘', '陈', '杨', '赵', '黄', '周', '吴'];
const names = ['伟', '芳', '娜', '秀英', '敏', '静', '丽', '强', '磊', '军'];
const surname = surnames[Math.floor(Math.random() * surnames.length)]!;
const name = names[Math.floor(Math.random() * names.length)]!;
return `${surname}${name}`;
}
static generateRandomChinesePhone(): string {
const prefixes = ['138', '139', '136', '137', '158', '159', '186', '187', '150', '151'];
const prefix = prefixes[Math.floor(Math.random() * prefixes.length)]!;
const suffix = Math.floor(Math.random() * 90000000 + 10000000);
return `${prefix}${suffix}`;
}
}