chore: remove old scripts directory (backed up to scripts.backup)
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
const { chromium } = require('playwright');
|
||||
const AxeBuilder = require('@axe-core/playwright').default;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
async function runAxeTest(url, pageName) {
|
||||
const browser = await chromium.launch();
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
const results = [];
|
||||
|
||||
try {
|
||||
await page.goto(url, { waitUntil: 'networkidle' });
|
||||
|
||||
const accessibilityScanResults = await new AxeBuilder({ page })
|
||||
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
|
||||
.analyze();
|
||||
|
||||
const violations = accessibilityScanResults.violations.map(v => ({
|
||||
id: v.id,
|
||||
impact: v.impact,
|
||||
description: v.description,
|
||||
help: v.help,
|
||||
helpUrl: v.helpUrl,
|
||||
nodes: v.nodes.length
|
||||
}));
|
||||
|
||||
const passes = accessibilityScanResults.passes.length;
|
||||
const incomplete = accessibilityScanResults.incomplete.length;
|
||||
|
||||
results.push({
|
||||
page: pageName,
|
||||
url,
|
||||
violations,
|
||||
passes,
|
||||
incomplete,
|
||||
score: calculateScore(violations, passes, incomplete)
|
||||
});
|
||||
|
||||
console.log(` ✅ 扫描完成: ${violations.length} 个违规, ${passes} 个通过, ${incomplete} 个未完成`);
|
||||
|
||||
await context.close();
|
||||
await browser.close();
|
||||
return results[0];
|
||||
|
||||
} catch (error) {
|
||||
await context.close();
|
||||
await browser.close();
|
||||
throw new Error(`可访问性测试失败: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateScore(violations, passes, incomplete) {
|
||||
const total = violations.length + passes + incomplete;
|
||||
if (total === 0) return 100;
|
||||
return ((passes / total) * 100).toFixed(1);
|
||||
}
|
||||
|
||||
function generateReport(results, outputPath) {
|
||||
const report = {
|
||||
timestamp: new Date().toISOString(),
|
||||
summary: {
|
||||
totalPages: results.length,
|
||||
totalViolations: results.reduce((sum, r) => sum + r.violations.length, 0),
|
||||
averageScore: (results.reduce((sum, r) => sum + parseFloat(r.score), 0) / results.length).toFixed(1)
|
||||
},
|
||||
pages: results
|
||||
};
|
||||
|
||||
fs.writeFileSync(outputPath, JSON.stringify(report, null, 2));
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
module.exports = { runAxeTest, generateReport };
|
||||
@@ -1,162 +0,0 @@
|
||||
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 };
|
||||
@@ -1,33 +0,0 @@
|
||||
const lighthouse = require('lighthouse').default;
|
||||
const chromeLauncher = require('chrome-launcher');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
async function runLighthouse(url, options = {}) {
|
||||
const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
|
||||
options.port = chrome.port;
|
||||
|
||||
const runnerResult = await lighthouse(url, options);
|
||||
await chrome.kill();
|
||||
|
||||
return runnerResult;
|
||||
}
|
||||
|
||||
function generateReport(result, outputPath) {
|
||||
const reportHtml = result.report;
|
||||
fs.writeFileSync(outputPath, reportHtml);
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
function extractMetrics(result) {
|
||||
const categories = result.lhr?.categories || {};
|
||||
return {
|
||||
performance: categories.performance?.score * 100 || 0,
|
||||
accessibility: categories.accessibility?.score * 100 || 0,
|
||||
bestPractices: categories['best-practices']?.score * 100 || 0,
|
||||
seo: categories.seo?.score * 100 || 0,
|
||||
pwa: categories.pwa?.score * 100 || 0
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { runLighthouse, generateReport, extractMetrics };
|
||||
@@ -1,136 +0,0 @@
|
||||
const { chromium } = require('playwright');
|
||||
const fs = require('fs');
|
||||
|
||||
class SEOValidator {
|
||||
constructor() {
|
||||
this.issues = [];
|
||||
}
|
||||
|
||||
async validatePage(url, pageName) {
|
||||
const browser = await chromium.launch();
|
||||
const page = await browser.newPage();
|
||||
|
||||
try {
|
||||
await page.goto(url, { waitUntil: 'networkidle' });
|
||||
|
||||
const checks = {
|
||||
title: this.checkTitle(page),
|
||||
description: this.checkDescription(page),
|
||||
headings: this.checkHeadings(page),
|
||||
images: this.checkImages(page),
|
||||
links: this.checkLinks(page),
|
||||
ogTags: this.checkOpenGraph(page),
|
||||
canonical: this.checkCanonical(page),
|
||||
h1: this.checkH1(page),
|
||||
lang: this.checkLanguage(page)
|
||||
};
|
||||
|
||||
const pageIssues = Object.entries(checks)
|
||||
.filter(([_, result]) => !result.passed)
|
||||
.map(([check, result]) => ({
|
||||
check,
|
||||
issue: result.issue,
|
||||
severity: result.severity
|
||||
}));
|
||||
|
||||
if (pageIssues.length > 0) {
|
||||
this.issues.push({
|
||||
page: pageName,
|
||||
url,
|
||||
issues: pageIssues
|
||||
});
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
return { checks, issues: pageIssues };
|
||||
|
||||
} catch (error) {
|
||||
await browser.close();
|
||||
throw new Error(`SEO验证失败: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
checkTitle(page) {
|
||||
return {
|
||||
passed: true,
|
||||
details: '需要手动验证'
|
||||
};
|
||||
}
|
||||
|
||||
checkDescription(page) {
|
||||
return {
|
||||
passed: true,
|
||||
details: '需要手动验证'
|
||||
};
|
||||
}
|
||||
|
||||
checkHeadings(page) {
|
||||
return {
|
||||
passed: true,
|
||||
details: '需要手动验证'
|
||||
};
|
||||
}
|
||||
|
||||
checkImages(page) {
|
||||
return {
|
||||
passed: true,
|
||||
details: '需要手动验证'
|
||||
};
|
||||
}
|
||||
|
||||
checkLinks(page) {
|
||||
return {
|
||||
passed: true,
|
||||
details: '需要手动验证'
|
||||
};
|
||||
}
|
||||
|
||||
checkOpenGraph(page) {
|
||||
return {
|
||||
passed: true,
|
||||
details: '需要手动验证'
|
||||
};
|
||||
}
|
||||
|
||||
checkCanonical(page) {
|
||||
return {
|
||||
passed: true,
|
||||
details: '需要手动验证'
|
||||
};
|
||||
}
|
||||
|
||||
checkH1(page) {
|
||||
return {
|
||||
passed: true,
|
||||
details: '需要手动验证'
|
||||
};
|
||||
}
|
||||
|
||||
checkLanguage(page) {
|
||||
return {
|
||||
passed: true,
|
||||
details: '需要手动验证'
|
||||
};
|
||||
}
|
||||
|
||||
getSummary() {
|
||||
const totalIssues = this.issues.reduce((sum, page) => sum + page.issues.length, 0);
|
||||
const pagesWithIssues = this.issues.length;
|
||||
|
||||
return {
|
||||
totalPages: this.issues.length + (this.issues.length === 0 ? 7 : 0),
|
||||
pagesWithIssues,
|
||||
totalIssues,
|
||||
severity: {
|
||||
high: this.issues.reduce((sum, page) =>
|
||||
sum + page.issues.filter(i => i.severity === 'high').length, 0),
|
||||
medium: this.issues.reduce((sum, page) =>
|
||||
sum + page.issues.filter(i => i.severity === 'medium').length, 0),
|
||||
low: this.issues.reduce((sum, page) =>
|
||||
sum + page.issues.filter(i => i.severity === 'low').length, 0)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { SEOValidator };
|
||||
Reference in New Issue
Block a user