Files
novalon-website/scripts/utils/form-tester.js
T
2026-03-06 10:07:52 +08:00

162 lines
5.5 KiB
JavaScript

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 };