fix(regression): resolve dogfood findings across marketing, auth, e2e and docs

- Fix list-to-detail navigation on product/service/solution/case pages
- Fix soft 404 on service detail by removing (marketing)/loading.tsx and using force-dynamic
- Fix contact form submission feedback and news placeholder image handling
- Unify SSR/client authentication state in auth.ts
- Add "新闻动态" to main navigation
- Fix Playwright storageState path and Firefox footer link flakiness
- Add E2E coverage for nav dropdown, cases filter and auth token parsing
- Update visual regression baselines (desktop/tablet/mobile, chromium/webkit/firefox)
- Update README, lessons-learned and add REGRESSION_REPORT_2026-07-27.md
- Ignore .lighthouseci/ and heading-hierarchy-report.json
This commit is contained in:
2026-07-27 07:39:11 +08:00
parent 10404dbb36
commit 2653a3730c
97 changed files with 659 additions and 187 deletions
+25 -32
View File
@@ -14,42 +14,35 @@ test.describe('网站全面测试验收', () => {
test('公司Logo可见且不被覆盖', async ({ page }) => {
const logo = page.locator('header img[alt*="睿新致远"], [data-testid="logo"]');
const logoCount = await logo.count();
async function assertLogoBoundingBox(logoLocator: ReturnType<typeof page.locator>) {
await expect(logoLocator).toBeVisible({ timeout: 10000 });
// 等待 layout 完成,避免 WebKit 中 boundingBox() 首次返回 null
const logoBox = await expect.poll(async () => logoLocator.boundingBox(), {
timeout: 5000,
intervals: [100, 200, 200],
}).not.toBeNull();
const header = page.locator('header');
const headerBox = await expect.poll(async () => header.boundingBox(), {
timeout: 5000,
intervals: [100, 200, 200],
}).not.toBeNull();
if (logoBox && headerBox) {
expect(logoBox.x).toBeGreaterThanOrEqual(headerBox.x);
expect(logoBox.y).toBeGreaterThanOrEqual(headerBox.y);
expect(logoBox.x + logoBox.width).toBeLessThanOrEqual(headerBox.x + headerBox.width);
expect(logoBox.y + logoBox.height).toBeLessThanOrEqual(headerBox.y + headerBox.height);
}
}
if (logoCount === 0) {
const allImages = page.locator('header img');
expect(await allImages.count()).toBeGreaterThan(0);
const firstLogo = allImages.first();
await expect(firstLogo).toBeVisible();
const logoBox = await firstLogo.boundingBox();
expect(logoBox).not.toBeNull();
const header = page.locator('header');
const headerBox = await header.boundingBox();
expect(headerBox).not.toBeNull();
if (logoBox && headerBox) {
expect(logoBox.x).toBeGreaterThanOrEqual(headerBox.x);
expect(logoBox.y).toBeGreaterThanOrEqual(headerBox.y);
expect(logoBox.x + logoBox.width).toBeLessThanOrEqual(headerBox.x + headerBox.width);
expect(logoBox.y + logoBox.height).toBeLessThanOrEqual(headerBox.y + headerBox.height);
}
await assertLogoBoundingBox(allImages.first());
} else {
await expect(logo.first()).toBeVisible();
const logoBox = await logo.first().boundingBox();
expect(logoBox).not.toBeNull();
const header = page.locator('header');
const headerBox = await header.boundingBox();
expect(headerBox).not.toBeNull();
if (logoBox && headerBox) {
expect(logoBox.x).toBeGreaterThanOrEqual(headerBox.x);
expect(logoBox.y).toBeGreaterThanOrEqual(headerBox.y);
expect(logoBox.x + logoBox.width).toBeLessThanOrEqual(headerBox.x + headerBox.width);
expect(logoBox.y + logoBox.height).toBeLessThanOrEqual(headerBox.y + headerBox.height);
}
await assertLogoBoundingBox(logo.first());
}
});