1. jest.setup.js: - 添加 Request/Response/Headers 全局对象 mock - 解决 'Request is not defined' 错误 2. .eslintrc.json: - 将 jest.setup.js 添加到忽略列表 3. shared-mocks.tsx: - 添加 ArrowUp 图标 mock 4. back-to-top.test.tsx: - 重写测试使用 import 语法 - 使用 fireEvent.scroll 触发滚动事件 - 修复组件渲染测试
This commit is contained in:
@@ -84,6 +84,7 @@ export const mockLucideReact = () => {
|
||||
jest.mock('lucide-react', () => ({
|
||||
ArrowRight: () => <span data-testid="arrow-right" />,
|
||||
ArrowLeft: () => <span data-testid="arrow-left" />,
|
||||
ArrowUp: () => <span data-testid="arrow-up" />,
|
||||
Shield: () => <span data-testid="shield-icon" />,
|
||||
Zap: () => <span data-testid="zap-icon" />,
|
||||
Award: () => <span data-testid="award-icon" />,
|
||||
|
||||
@@ -1,43 +1,58 @@
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
|
||||
import { BackToTop } from './back-to-top';
|
||||
|
||||
// Mock useReducedMotion
|
||||
jest.mock('@/hooks/use-reduced-motion', () => ({
|
||||
useReducedMotion: () => false,
|
||||
}));
|
||||
|
||||
// Mock AnimatePresence to always render children
|
||||
jest.mock('framer-motion', () => ({
|
||||
...jest.requireActual('framer-motion'),
|
||||
AnimatePresence: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
||||
motion: {
|
||||
button: ({ children, ...props }: React.ComponentProps<'button'>) => <button {...props}>{children}</button>,
|
||||
},
|
||||
useAnimation: () => ({
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
}),
|
||||
useMotionValue: () => ({
|
||||
get: jest.fn(),
|
||||
set: jest.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('lucide-react', () => ({
|
||||
ArrowUp: () => <span data-testid="arrow-up-icon" />,
|
||||
}));
|
||||
|
||||
describe('BackToTop', () => {
|
||||
let scrollYValue = 0;
|
||||
const originalScrollY = Object.getOwnPropertyDescriptor(window, 'scrollY');
|
||||
const originalScrollTo = window.scrollTo;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
scrollYValue = 0;
|
||||
|
||||
Object.defineProperty(window, 'scrollY', {
|
||||
get: () => scrollYValue,
|
||||
configurable: true,
|
||||
});
|
||||
|
||||
window.scrollTo = jest.fn();
|
||||
window.addEventListener = jest.fn((event, handler) => {
|
||||
if (event === 'scroll') {
|
||||
// 模拟滚动事件触发
|
||||
(handler as EventListener)(new Event('scroll'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (originalScrollY) {
|
||||
Object.defineProperty(window, 'scrollY', originalScrollY);
|
||||
}
|
||||
window.scrollTo = originalScrollTo;
|
||||
});
|
||||
|
||||
it('should not render when scroll position is less than 500px', () => {
|
||||
scrollYValue = 0;
|
||||
const { container } = render(<BackToTop />);
|
||||
expect(container.firstChild).toBeNull();
|
||||
expect(container.querySelector('button')).toBeNull();
|
||||
});
|
||||
|
||||
it('should render button when scroll position is more than 500px', async () => {
|
||||
@@ -45,8 +60,12 @@ describe('BackToTop', () => {
|
||||
|
||||
render(<BackToTop />);
|
||||
|
||||
act(() => {
|
||||
fireEvent.scroll(window);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
const button = screen.getByRole('button', { name: /返回顶部/i });
|
||||
const button = screen.queryByRole('button', { name: /返回顶部/i });
|
||||
expect(button).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -56,11 +75,14 @@ describe('BackToTop', () => {
|
||||
|
||||
render(<BackToTop />);
|
||||
|
||||
await waitFor(() => {
|
||||
const button = screen.getByRole('button', { name: /返回顶部/i });
|
||||
fireEvent.click(button);
|
||||
act(() => {
|
||||
fireEvent.scroll(window);
|
||||
});
|
||||
|
||||
const button = await screen.findByRole('button', { name: /返回顶部/i });
|
||||
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(window.scrollTo).toHaveBeenCalledWith({
|
||||
top: 0,
|
||||
behavior: 'smooth',
|
||||
@@ -72,10 +94,12 @@ describe('BackToTop', () => {
|
||||
|
||||
render(<BackToTop />);
|
||||
|
||||
await waitFor(() => {
|
||||
const button = screen.getByRole('button');
|
||||
expect(button).toHaveAttribute('aria-label', '返回顶部');
|
||||
expect(button).toHaveAttribute('title', '返回顶部');
|
||||
act(() => {
|
||||
fireEvent.scroll(window);
|
||||
});
|
||||
|
||||
const button = await screen.findByRole('button');
|
||||
expect(button).toHaveAttribute('aria-label', '返回顶部');
|
||||
expect(button).toHaveAttribute('title', '返回顶部');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user