feat(ui/ux): 优化用户体验和可访问性
- 字体加载优化: 添加 font-display: block 策略,创建 useFontLoading hook - 色彩对比度: 调整 text-muted 和 text-tertiary 颜色值确保 WCAG AA 合规 - 滚动进度条: 新增 ScrollProgress 组件,支持 reduced motion - 表单自动保存: 新增 useFormAutosave hook,防止用户数据丢失 - 返回顶部按钮: 新增 BackToTop 组件,提升长页面导航体验 - 图片懒加载: 优化 OptimizedImage 组件,添加 blur placeholder 和加载动画 所有新组件均包含完整测试,1450+ 测试通过
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { ScrollProgress } from './scroll-progress';
|
||||
|
||||
// Mock framer-motion
|
||||
jest.mock('framer-motion', () => ({
|
||||
motion: {
|
||||
div: ({ children, ...props }: React.ComponentProps<'div'>) => <div {...props}>{children}</div>,
|
||||
},
|
||||
useScroll: () => ({ scrollYProgress: { get: () => 0, onChange: jest.fn() } }),
|
||||
useSpring: () => ({ get: () => 0 }),
|
||||
}));
|
||||
|
||||
// Mock useReducedMotion
|
||||
jest.mock('@/hooks/use-reduced-motion', () => ({
|
||||
useReducedMotion: () => false,
|
||||
}));
|
||||
|
||||
describe('ScrollProgress', () => {
|
||||
let scrollYValue = 0;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
scrollYValue = 0;
|
||||
Object.defineProperty(window, 'scrollY', {
|
||||
get: () => scrollYValue,
|
||||
configurable: true,
|
||||
});
|
||||
window.addEventListener = jest.fn((event, handler) => {
|
||||
if (event === 'scroll') {
|
||||
(handler as EventListener)(new Event('scroll'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should not render when scroll position is less than 100px', () => {
|
||||
scrollYValue = 0;
|
||||
const { container } = render(<ScrollProgress />);
|
||||
expect(container.firstChild).toBeNull();
|
||||
});
|
||||
|
||||
it('should render progressbar with correct ARIA attributes when visible', async () => {
|
||||
scrollYValue = 150;
|
||||
|
||||
render(<ScrollProgress />);
|
||||
|
||||
await waitFor(() => {
|
||||
const progressbar = screen.getByRole('progressbar');
|
||||
expect(progressbar).toBeInTheDocument();
|
||||
expect(progressbar).toHaveAttribute('aria-label', '页面滚动进度');
|
||||
expect(progressbar).toHaveAttribute('aria-valuemin', '0');
|
||||
expect(progressbar).toHaveAttribute('aria-valuemax', '100');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user