feat: 添加面包屑导航组件并优化页面布局

refactor: 重构页面结构和导航逻辑

fix: 修复移动端菜单导航和滚动行为

perf: 优化图片加载性能和资源请求

test: 添加端到端测试和性能测试用例

docs: 更新.gitignore文件

chore: 更新依赖和配置

style: 优化代码格式和类型安全

ci: 调整Playwright测试超时时间

build: 更新Next.js配置和构建选项
This commit is contained in:
张翔
2026-02-28 09:09:04 +08:00
parent 9d01e0982f
commit 9451814ca4
60 changed files with 4078 additions and 148 deletions
@@ -0,0 +1,230 @@
import { test, expect } from '../../fixtures/base.fixture';
test.describe('Error Handling E2E Tests', () => {
test.describe('404 Page', () => {
test('404 page displays correctly for non-existent routes', async ({ page }) => {
await page.goto('/this-page-does-not-exist');
await page.waitForLoadState('load');
await expect(page.locator('h1')).toContainText('404');
await expect(page.locator('h2')).toContainText('页面未找到');
const returnHomeButton = page.getByRole('link', { name: '返回首页' });
await expect(returnHomeButton).toBeVisible();
await returnHomeButton.click();
await page.waitForURL('/');
await expect(page).toHaveURL('/');
});
test('404 page provides helpful navigation links', async ({ page }) => {
await page.goto('/non-existent-page');
await page.waitForLoadState('load');
const aboutLink = page.getByRole('link', { name: '关于我们' });
const servicesLink = page.getByRole('link', { name: '核心业务' });
const productsLink = page.getByRole('link', { name: '产品服务' });
const casesLink = page.getByRole('link', { name: '成功案例' });
await expect(aboutLink).toBeVisible();
await expect(servicesLink).toBeVisible();
await expect(productsLink).toBeVisible();
await expect(casesLink).toBeVisible();
await aboutLink.click();
await page.waitForURL('/about');
await expect(page).toHaveURL('/about');
});
test('404 page back button works correctly', async ({ page }) => {
await page.goto('/about');
await page.waitForLoadState('load');
await page.goto('/non-existent-page');
await page.waitForLoadState('load');
const backButton = page.getByRole('button', { name: '返回上一页' });
await backButton.click();
await page.waitForURL('/about');
await expect(page).toHaveURL('/about');
});
test('404 page contact link works', async ({ page }) => {
await page.goto('/another-404-page');
await page.waitForLoadState('load');
const contactLink = page.getByRole('link', { name: '联系我们' });
await contactLink.click();
await page.waitForURL('/contact');
await expect(page).toHaveURL('/contact');
});
});
test.describe('Error Page', () => {
test('Error page displays correctly when error occurs', async ({ page }) => {
await page.goto('/error-test');
await page.waitForLoadState('load');
await expect(page.locator('h1')).toContainText('出现了一些问题');
await expect(page.getByRole('button', { name: '重试' })).toBeVisible();
await expect(page.getByRole('link', { name: '返回首页' })).toBeVisible();
});
test('Error page retry button works', async ({ page }) => {
await page.goto('/error-test');
await page.waitForLoadState('load');
const retryButton = page.getByRole('button', { name: '重试' });
await retryButton.click();
await page.waitForLoadState('load');
await expect(page).toHaveURL('/error-test');
});
test('Error page home button works', async ({ page }) => {
await page.goto('/error-test');
await page.waitForLoadState('load');
const homeButton = page.getByRole('link', { name: '返回首页' });
await homeButton.click();
await page.waitForURL('/');
await expect(page).toHaveURL('/');
});
test('Error page provides helpful links', async ({ page }) => {
await page.goto('/error-test');
await page.waitForLoadState('load');
const contactLink = page.getByRole('link', { name: '联系我们' });
const servicesLink = page.getByRole('link', { name: '核心业务' });
await expect(contactLink).toBeVisible();
await expect(servicesLink).toBeVisible();
await contactLink.click();
await page.waitForURL('/contact');
await expect(page).toHaveURL('/contact');
});
});
test.describe('Error Boundary Integration', () => {
test('Error boundary catches client-side errors', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('load');
await page.evaluate(() => {
throw new Error('Test error for error boundary');
});
await page.waitForLoadState('load');
await expect(page.locator('h1')).toContainText('出现了一些问题');
});
test('Error boundary provides recovery options', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('load');
await page.evaluate(() => {
throw new Error('Test error for recovery');
});
await page.waitForLoadState('load');
const retryButton = page.getByRole('button', { name: '重试' });
await expect(retryButton).toBeVisible();
const homeButton = page.getByRole('link', { name: '返回首页' });
await expect(homeButton).toBeVisible();
});
});
test.describe('Navigation Error Recovery', () => {
test('Broken links redirect to 404 page', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('load');
await page.evaluate(() => {
const link = document.createElement('a');
link.href = '/broken-link';
link.textContent = 'Broken Link';
document.body.appendChild(link);
link.click();
});
await page.waitForLoadState('load');
await expect(page.locator('h1')).toContainText('404');
});
test('Users can navigate away from error pages', async ({ page }) => {
await page.goto('/non-existent');
await page.waitForLoadState('load');
await page.goto('/about');
await page.waitForLoadState('load');
await expect(page.locator('h1')).toContainText('关于我们');
await expect(page).toHaveURL('/about');
});
});
test.describe('Error Page Accessibility', () => {
test('404 page is keyboard navigable', async ({ page }) => {
await page.goto('/404-test');
await page.waitForLoadState('load');
await page.keyboard.press('Tab');
await expect(page.getByRole('link', { name: '返回首页' })).toBeFocused();
await page.keyboard.press('Enter');
await page.waitForURL('/');
await expect(page).toHaveURL('/');
});
test('Error page is keyboard navigable', async ({ page }) => {
await page.goto('/error-test');
await page.waitForLoadState('load');
await page.keyboard.press('Tab');
await expect(page.getByRole('button', { name: '重试' })).toBeFocused();
await page.keyboard.press('Enter');
await page.waitForLoadState('load');
});
test('Error pages have proper ARIA labels', async ({ page }) => {
await page.goto('/404-test');
await page.waitForLoadState('load');
const main = page.locator('main');
await expect(main).toHaveAttribute('role', 'main');
const heading = page.locator('h1');
await expect(heading).toBeVisible();
});
});
test.describe('Error Page Performance', () => {
test('404 page loads quickly', async ({ page }) => {
const startTime = Date.now();
await page.goto('/fast-404');
await page.waitForLoadState('load');
const loadTime = Date.now() - startTime;
expect(loadTime).toBeLessThan(3000);
});
test('Error page loads quickly', async ({ page }) => {
const startTime = Date.now();
await page.goto('/error-test');
await page.waitForLoadState('load');
const loadTime = Date.now() - startTime;
expect(loadTime).toBeLessThan(3000);
});
});
});