diff --git a/scripts/form-validation.js b/scripts/form-validation.js new file mode 100644 index 0000000..129b6fe --- /dev/null +++ b/scripts/form-validation.js @@ -0,0 +1,32 @@ +const { FormTester } = require('./utils/form-tester'); +const fs = require('fs'); + +async function main() { + console.log('📝 开始表单验证...\n'); + + const tester = new FormTester(); + + console.log('📄 测试联系表单\n'); + const result = await tester.testContactForm(); + tester.results.push(result); + + const summary = tester.getSummary(); + + console.log('\n📊 表单验证摘要\n'); + console.log('─'.repeat(80)); + console.log(`总表单数: ${summary.totalForms}`); + console.log(`总测试数: ${summary.totalTests}`); + console.log(`通过测试: ${summary.passedTests}`); + console.log(`通过率: ${summary.passRate}%`); + console.log('─'.repeat(80)); + + const outputPath = 'test-results/form-validation-summary.json'; + fs.writeFileSync(outputPath, JSON.stringify({ + timestamp: new Date().toISOString(), + summary, + results: tester.results + }, null, 2)); + console.log(`\n💾 详细结果已保存到: ${outputPath}`); +} + +main().catch(console.error); \ No newline at end of file diff --git a/scripts/utils/form-tester.js b/scripts/utils/form-tester.js new file mode 100644 index 0000000..3dece75 --- /dev/null +++ b/scripts/utils/form-tester.js @@ -0,0 +1,162 @@ +const { chromium } = require('playwright'); +const fs = require('fs'); + +class FormTester { + constructor() { + this.results = []; + } + + async testContactForm() { + const browser = await chromium.launch(); + const page = await browser.newPage(); + + try { + await page.goto('http://localhost:3000/contact', { waitUntil: 'networkidle' }); + + const form = { + nameInput: page.locator('[data-testid="name-input"]'), + phoneInput: page.locator('[data-testid="phone-input"]'), + emailInput: page.locator('[data-testid="email-input"]'), + subjectInput: page.locator('[data-testid="subject-input"]'), + messageInput: page.locator('[data-testid="message-input"]'), + submitButton: page.locator('[data-testid="submit-button"]') + }; + + console.log(' 📝 测试表单字段可见性...'); + + const visibilityTests = [ + { name: '姓名输入框', element: form.nameInput }, + { name: '电话输入框', element: form.phoneInput }, + { name: '邮箱输入框', element: form.emailInput }, + { name: '主题输入框', element: form.subjectInput }, + { name: '消息输入框', element: form.messageInput }, + { name: '提交按钮', element: form.submitButton } + ]; + + const visibilityResults = []; + for (const test of visibilityTests) { + try { + await test.element.waitFor({ state: 'visible', timeout: 5000 }); + visibilityResults.push({ name: test.name, passed: true }); + console.log(` ✅ ${test.name} 可见`); + } catch (error) { + visibilityResults.push({ name: test.name, passed: false, error: error.message }); + console.log(` ❌ ${test.name} 不可见: ${error.message}`); + } + } + + console.log(' 📝 测试表单验证...'); + + const validationTests = [ + { + name: '必填字段验证', + test: async () => { + await form.submitButton.click(); + const errorMessages = await page.locator('[data-testid*="error"]').count(); + return errorMessages > 0; + } + }, + { + name: '邮箱格式验证', + test: async () => { + await form.emailInput.fill('invalid-email'); + await form.emailInput.blur(); + const error = await page.locator('[data-testid="email-input"] + [data-testid*="error"]').isVisible(); + return error; + } + }, + { + name: '电话格式验证', + test: async () => { + await form.phoneInput.fill('123'); + await form.phoneInput.blur(); + const error = await page.locator('[data-testid="phone-input"] + [data-testid*="error"]').isVisible(); + return error; + } + } + ]; + + const validationResults = []; + for (const test of validationTests) { + try { + await page.reload(); + await page.waitForLoadState('networkidle'); + const passed = await test.test(); + validationResults.push({ name: test.name, passed }); + console.log(` ${passed ? '✅' : '❌'} ${test.name}`); + } catch (error) { + validationResults.push({ name: test.name, passed: false, error: error.message }); + console.log(` ❌ ${test.name}: ${error.message}`); + } + } + + console.log(' 📝 测试表单提交...'); + + const submitTest = { + name: '表单提交', + test: async () => { + await form.nameInput.fill('测试用户'); + await form.phoneInput.fill('13800138000'); + await form.emailInput.fill('test@example.com'); + await form.subjectInput.fill('测试主题'); + await form.messageInput.fill('这是一条测试消息'); + await form.submitButton.click(); + + await page.waitForTimeout(2000); + + const successMessage = await page.locator('[data-testid*="success"]').isVisible(); + const errorMessage = await page.locator('[data-testid*="error"]').isVisible(); + + if (successMessage) { + return { passed: true, message: '提交成功' }; + } else if (errorMessage) { + return { passed: false, message: '提交失败' }; + } else { + return { passed: true, message: '表单已提交(需后端验证)' }; + } + } + }; + + let submitResult; + try { + submitResult = await submitTest.test(); + console.log(` ${submitResult.passed ? '✅' : '❌'} ${submitResult.name}: ${submitResult.message}`); + } catch (error) { + submitResult = { passed: false, error: error.message }; + console.log(` ❌ ${submitTest.name}: ${error.message}`); + } + + await browser.close(); + + return { + page: '联系我们', + url: 'http://localhost:3000/contact', + visibility: visibilityResults, + validation: validationResults, + submit: submitResult + }; + + } catch (error) { + await browser.close(); + throw new Error(`表单测试失败: ${error.message}`); + } + } + + getSummary() { + const totalTests = this.results.reduce((sum, r) => + sum + r.visibility.length + r.validation.length + 1, 0); + const passedTests = this.results.reduce((sum, r) => + sum + r.visibility.filter(t => t.passed).length + + r.validation.filter(t => t.passed).length + + (r.submit?.passed ? 1 : 0), 0); + + return { + totalForms: this.results.length, + totalTests, + passedTests, + passRate: ((passedTests / totalTests) * 100).toFixed(1) + }; + } +} + +module.exports = { FormTester }; \ No newline at end of file