docs(test): 添加设计文档、测试规范与 E2E 测试套件

- 新增 ADR 架构决策记录 (Design DNA 集成与深化)
- 新增 CMS 系统设计文档
- 新增实施计划文档 (Phase1-3)
- 新增 Bain 品牌升级设计规格
- 新增 E2E 分层测试套件 (P1-P4)
- 新增视觉回归测试配置
- 新增光效分析、视觉验证等辅助脚本
- 更新验收测试报告
This commit is contained in:
张翔
2026-07-07 06:54:25 +08:00
parent 8def296301
commit 636bc4ecde
31 changed files with 9262 additions and 41 deletions
+206
View File
@@ -0,0 +1,206 @@
import { chromium } from '@playwright/test';
async function runDetailedCheck() {
console.log('========================================');
console.log(' Detailed Glow & Text Check');
console.log('========================================');
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
viewport: { width: 1440, height: 1080 },
});
const page = await context.newPage();
await page.goto('http://localhost:3000', { waitUntil: 'domcontentloaded' });
await page.waitForTimeout(2000);
console.log('\n1. Checking Hero section text visibility...');
const heroTextInfo = await page.evaluate(() => {
const heroSection = document.querySelector('section.min-h-screen');
if (!heroSection) return { error: 'Hero section not found' };
const headings = heroSection.querySelectorAll('h1, h2, p, span');
const textElements = [];
headings.forEach((el) => {
const style = window.getComputedStyle(el);
const rect = el.getBoundingClientRect();
if (rect.width > 50 && rect.height > 20) {
textElements.push({
tag: el.tagName,
text: el.textContent?.trim().substring(0, 50) || '',
opacity: style.opacity,
color: style.color,
zIndex: style.zIndex || 'auto',
position: style.position,
mixBlendMode: style.mixBlendMode,
y: Math.round(rect.top),
height: Math.round(rect.height),
});
}
});
return textElements.slice(0, 10);
});
console.log(` Found ${heroTextInfo.length} text elements in Hero:`);
heroTextInfo.forEach((el, i) => {
console.log(` ${i + 1}. ${el.tag}: "${el.text}"`);
console.log(` opacity: ${el.opacity}, color: ${el.color.substring(0, 30)}`);
console.log(` position: ${el.position}, zIndex: ${el.zIndex}`);
});
console.log('\n2. Checking Stats section (可衡量成果)...');
await page.evaluate(() => {
const statsSection = document.querySelector('section.bg-ink-light');
if (statsSection) {
statsSection.scrollIntoView({ behavior: 'auto' });
}
});
await page.waitForTimeout(1000);
const statsInfo = await page.evaluate(() => {
const statsSection = document.querySelector('section.bg-ink-light');
if (!statsSection) return { error: 'Stats section not found' };
const glowElements = [];
const allElements = statsSection.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.01) {
const rect = el.getBoundingClientRect();
if (rect.width > 50 && rect.height > 50) {
glowElements.push({
tag: el.tagName,
className: el.className.substring(0, 80),
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,
});
}
}
});
const textElements = [];
const texts = statsSection.querySelectorAll('h2, h3, p, span, div');
texts.forEach((el) => {
const style = window.getComputedStyle(el);
const rect = el.getBoundingClientRect();
const text = el.textContent?.trim() || '';
if (text.length > 5 && rect.width > 30 && rect.height > 15) {
textElements.push({
text: text.substring(0, 40),
color: style.color,
opacity: style.opacity,
});
}
});
return {
glowCount: glowElements.length,
glowElements: glowElements.slice(0, 8),
textSample: textElements.slice(0, 5),
};
});
console.log(` Glow/blur elements in Stats: ${statsInfo.glowCount}`);
if (statsInfo.glowElements?.length > 0) {
statsInfo.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}`);
});
} else {
console.log(' ✓ No glow/blur elements found in Stats section (good!)');
}
console.log('\n3. Checking Case Studies section...');
await page.evaluate(() => {
const sections = document.querySelectorAll('section');
let caseSection = null;
sections.forEach((s) => {
if (s.textContent?.includes('可衡量的业务成果') || s.textContent?.includes('Case Studies')) {
caseSection = s;
}
});
if (caseSection) {
caseSection.scrollIntoView({ behavior: 'auto' });
}
});
await page.waitForTimeout(1000);
const caseInfo = await page.evaluate(() => {
const sections = document.querySelectorAll('section');
let caseSection = null;
sections.forEach((s) => {
if (s.textContent?.includes('可衡量的业务成果') || s.textContent?.includes('Case Studies')) {
caseSection = s;
}
});
if (!caseSection) return { error: 'Case section not found' };
const cards = caseSection.querySelectorAll('.group, a[href]');
const cardInfo = [];
cards.forEach((card, index) => {
const style = window.getComputedStyle(card);
const rect = card.getBoundingClientRect();
if (rect.width > 200 && rect.height > 100) {
const glowElementsInside = [];
const insideElements = card.querySelectorAll('*');
insideElements.forEach((el) => {
const elStyle = window.getComputedStyle(el);
if (elStyle.filter.includes('blur') && elStyle.backgroundImage.includes('radial-gradient')) {
glowElementsInside.push({
opacity: elStyle.opacity,
className: el.className.substring(0, 60),
});
}
});
cardInfo.push({
index: index + 1,
size: `${Math.round(rect.width)}x${Math.round(rect.height)}`,
glowInside: glowElementsInside.length,
glowElements: glowElementsInside.slice(0, 3),
});
}
});
return {
cardCount: cardInfo.length,
cards: cardInfo.slice(0, 4),
};
});
console.log(` Found ${caseInfo.cardCount} cards in Case Studies`);
if (caseInfo.cards) {
caseInfo.cards.forEach((card) => {
console.log(` Card ${card.index}: ${card.size}, glow elements: ${card.glowInside}`);
card.glowElements?.forEach((glow, i) => {
console.log(` - glow-${i + 1}: opacity ${glow.opacity}`);
});
});
}
await browser.close();
console.log('\n========================================');
console.log(' Detailed Check Complete');
console.log('========================================');
}
runDetailedCheck().catch(console.error);