docs(test): 添加设计文档、测试规范与 E2E 测试套件
- 新增 ADR 架构决策记录 (Design DNA 集成与深化) - 新增 CMS 系统设计文档 - 新增实施计划文档 (Phase1-3) - 新增 Bain 品牌升级设计规格 - 新增 E2E 分层测试套件 (P1-P4) - 新增视觉回归测试配置 - 新增光效分析、视觉验证等辅助脚本 - 更新验收测试报告
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
import { chromium } from '@playwright/test';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const screenshotsDir = '/tmp/screenshots/final-visual-test';
|
||||
fs.mkdirSync(screenshotsDir, { recursive: true });
|
||||
|
||||
async function runTests() {
|
||||
console.log('========================================');
|
||||
console.log(' Novalon Homepage Visual Test');
|
||||
console.log('========================================');
|
||||
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const context = await browser.newContext({
|
||||
viewport: { width: 1440, height: 1080 },
|
||||
});
|
||||
const page = await context.newPage();
|
||||
|
||||
console.log('\n1. Loading homepage...');
|
||||
await page.goto('http://localhost:3000', { waitUntil: 'domcontentloaded' });
|
||||
await page.waitForTimeout(2000);
|
||||
console.log(' ✓ Page loaded');
|
||||
|
||||
console.log('\n2. Capturing full page screenshot...');
|
||||
await page.screenshot({
|
||||
path: path.join(screenshotsDir, '01-home-full.png'),
|
||||
fullPage: true,
|
||||
});
|
||||
console.log(' ✓ Full page captured');
|
||||
|
||||
const sections = [
|
||||
{ name: '02-hero', scrollY: 0, desc: 'Hero Section' },
|
||||
{ name: '03-stats', scrollY: 900, desc: 'Stats Section (可衡量成果)' },
|
||||
{ name: '04-services', scrollY: 1800, desc: 'Services Matrix' },
|
||||
{ name: '05-industries', scrollY: 2800, desc: 'Industries Section' },
|
||||
{ name: '06-cases', scrollY: 3600, desc: 'Case Studies' },
|
||||
{ name: '07-approach', scrollY: 4500, desc: 'Approach Section' },
|
||||
{ name: '08-insights', scrollY: 5400, desc: 'Insights Section' },
|
||||
{ name: '09-cta', scrollY: 6300, desc: 'CTA Section' },
|
||||
];
|
||||
|
||||
console.log('\n3. Capturing section screenshots...');
|
||||
for (const section of sections) {
|
||||
await page.evaluate((scrollY) => {
|
||||
window.scrollTo(0, scrollY);
|
||||
}, section.scrollY);
|
||||
await page.waitForTimeout(800);
|
||||
|
||||
await page.screenshot({
|
||||
path: path.join(screenshotsDir, `${section.name}.png`),
|
||||
});
|
||||
console.log(` ✓ ${section.desc}`);
|
||||
}
|
||||
|
||||
console.log('\n4. Checking text readability...');
|
||||
const textIssues = await page.evaluate(() => {
|
||||
const issues = [];
|
||||
const allElements = document.querySelectorAll('*');
|
||||
|
||||
allElements.forEach((el) => {
|
||||
const style = window.getComputedStyle(el);
|
||||
const opacity = parseFloat(style.opacity);
|
||||
const mixBlendMode = style.mixBlendMode;
|
||||
|
||||
if (mixBlendMode && mixBlendMode !== 'normal') {
|
||||
const rect = el.getBoundingClientRect();
|
||||
if (rect.width > 50 && rect.height > 20) {
|
||||
issues.push({
|
||||
type: 'mix-blend-mode',
|
||||
tag: el.tagName,
|
||||
className: el.className.substring(0, 80),
|
||||
blendMode: mixBlendMode,
|
||||
text: el.textContent?.trim().substring(0, 40) || '',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (opacity < 0.5 && opacity > 0) {
|
||||
const rect = el.getBoundingClientRect();
|
||||
if (rect.width > 100 && rect.height > 30 && el.textContent?.trim().length > 10) {
|
||||
issues.push({
|
||||
type: 'low-opacity-text',
|
||||
tag: el.tagName,
|
||||
className: el.className.substring(0, 80),
|
||||
opacity: opacity.toFixed(2),
|
||||
text: el.textContent.trim().substring(0, 40),
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return issues.slice(0, 20);
|
||||
});
|
||||
|
||||
if (textIssues.length > 0) {
|
||||
console.log(` ⚠ Found ${textIssues.length} potential issues:`);
|
||||
textIssues.forEach((issue, i) => {
|
||||
console.log(` ${i + 1}. [${issue.type}] ${issue.tag}: "${issue.text}"`);
|
||||
if (issue.blendMode) console.log(` blendMode: ${issue.blendMode}`);
|
||||
if (issue.opacity) console.log(` opacity: ${issue.opacity}`);
|
||||
});
|
||||
} else {
|
||||
console.log(' ✓ No major text readability issues');
|
||||
}
|
||||
|
||||
console.log('\n5. Checking glow/blur elements...');
|
||||
const glowElements = await page.evaluate(() => {
|
||||
const elements = [];
|
||||
const allElements = document.querySelectorAll('*');
|
||||
|
||||
allElements.forEach((el) => {
|
||||
const style = window.getComputedStyle(el);
|
||||
const hasBlur = style.filter.includes('blur');
|
||||
const hasRadialGradient = style.backgroundImage.includes('radial-gradient');
|
||||
const opacity = parseFloat(style.opacity);
|
||||
|
||||
if ((hasBlur || hasRadialGradient) && opacity > 0.03) {
|
||||
const rect = el.getBoundingClientRect();
|
||||
if (rect.width > 150 && rect.height > 150) {
|
||||
elements.push({
|
||||
tag: el.tagName,
|
||||
className: el.className.substring(0, 100),
|
||||
opacity: opacity.toFixed(3),
|
||||
hasBlur,
|
||||
hasRadialGradient,
|
||||
size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
|
||||
position: style.position,
|
||||
zIndex: style.zIndex || 'auto',
|
||||
pointerEvents: style.pointerEvents,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return elements.sort((a, b) => parseFloat(b.opacity) - parseFloat(a.opacity)).slice(0, 12);
|
||||
});
|
||||
|
||||
console.log(` Found ${glowElements.length} significant glow/blur elements:`);
|
||||
glowElements.forEach((el, i) => {
|
||||
const type = el.hasBlur && el.hasRadialGradient ? 'blur+gradient' : el.hasBlur ? 'blur' : 'gradient';
|
||||
console.log(` ${i + 1}. ${el.tag} (${el.size}, ${type}, opacity: ${el.opacity})`);
|
||||
console.log(` position: ${el.position}, zIndex: ${el.zIndex}, pointerEvents: ${el.pointerEvents}`);
|
||||
console.log(` class: ${el.className.substring(0, 60)}`);
|
||||
});
|
||||
|
||||
await browser.close();
|
||||
|
||||
console.log('\n========================================');
|
||||
console.log(' Test Complete');
|
||||
console.log('========================================');
|
||||
console.log(` Screenshots saved to: ${screenshotsDir}`);
|
||||
console.log('\n To view screenshots:');
|
||||
console.log(` open ${screenshotsDir}`);
|
||||
console.log('========================================');
|
||||
}
|
||||
|
||||
runTests().catch(console.error);
|
||||
Reference in New Issue
Block a user