diff --git a/e2e/src/data/test-data.ts b/e2e/src/data/test-data.ts new file mode 100644 index 0000000..164e19c --- /dev/null +++ b/e2e/src/data/test-data.ts @@ -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: '', 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: [ + '', + '', + '', + 'javascript: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', +}; diff --git a/e2e/src/utils/TestDataGenerator.ts b/e2e/src/utils/TestDataGenerator.ts index d9fd0f1..6a472cf 100644 --- a/e2e/src/utils/TestDataGenerator.ts +++ b/e2e/src/utils/TestDataGenerator.ts @@ -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: [ + '', + '', + '', + 'javascript: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}`; + } }