// Setting.test.jsx | |
import React from 'react'; | |
import { render, screen, waitFor, fireEvent } from '@testing-library/react'; | |
import { MemoryRouter, useNavigate, useLocation } from 'react-router-dom'; | |
import Setting from './Setting'; | |
import { getUserInfo, updatePassword } from '../../api/personal'; | |
// Mock API 调用 | |
jest.mock('../../api/personal', () => ({ | |
getUserInfo: jest.fn(), | |
updatePassword: jest.fn() | |
})); | |
// Mock react-router-dom hooks | |
jest.mock('react-router-dom', () => ({ | |
...jest.requireActual('react-router-dom'), | |
useNavigate: jest.fn(), | |
useLocation: jest.fn() | |
})); | |
describe('Setting Component', () => { | |
const mockNavigate = jest.fn(); | |
const mockLocation = { | |
pathname: '/personal/setting', | |
state: { dashboardTab: 'settings' } | |
}; | |
beforeEach(() => { | |
useNavigate.mockReturnValue(mockNavigate); | |
useLocation.mockReturnValue(mockLocation); | |
// 重置所有 mock | |
jest.clearAllMocks(); | |
// 设置默认 mock 返回值 | |
getUserInfo.mockResolvedValue({ | |
username: 'testuser', | |
email: 'test@example.com' | |
}); | |
updatePassword.mockResolvedValue({ success: true }); | |
}); | |
it('应该正确加载并显示用户信息', async () => { | |
render( | |
<MemoryRouter> | |
<Setting /> | |
</MemoryRouter> | |
); | |
await waitFor(() => { | |
expect(screen.getByText('个人设置')).toBeInTheDocument(); | |
expect(screen.getByText('账户信息')).toBeInTheDocument(); | |
expect(screen.getByText('用户名:')).toBeInTheDocument(); | |
expect(screen.getByText('testuser')).toBeInTheDocument(); | |
expect(screen.getByRole('heading', { name: '修改密码' })).toBeInTheDocument(); | |
}); | |
}); | |
it('应该处理密码修改表单提交', async () => { | |
render( | |
<MemoryRouter> | |
<Setting /> | |
</MemoryRouter> | |
); | |
// 填写表单 | |
fireEvent.change(screen.getByLabelText('原密码:'), { | |
target: { value: 'oldpassword123' } | |
}); | |
fireEvent.change(screen.getByLabelText('新密码:'), { | |
target: { value: 'newpassword123' } | |
}); | |
fireEvent.change(screen.getByLabelText('确认新密码:'), { | |
target: { value: 'newpassword123' } | |
}); | |
// 提交表单 | |
fireEvent.click(screen.getByRole('button', { name: '修改密码' })); | |
await waitFor(() => { | |
expect(updatePassword).toHaveBeenCalledWith('oldpassword123', 'newpassword123'); | |
expect(screen.getByText('密码修改成功')).toBeInTheDocument(); | |
}); | |
}); | |
it('应该处理API错误', async () => { | |
updatePassword.mockRejectedValue(new Error('原密码不正确')); | |
render( | |
<MemoryRouter> | |
<Setting /> | |
</MemoryRouter> | |
); | |
// 填写表单 | |
fireEvent.change(screen.getByLabelText('原密码:'), { | |
target: { value: 'wrongpassword' } | |
}); | |
fireEvent.change(screen.getByLabelText('新密码:'), { | |
target: { value: 'newpassword123' } | |
}); | |
fireEvent.change(screen.getByLabelText('确认新密码:'), { | |
target: { value: 'newpassword123' } | |
}); | |
// 提交表单 | |
fireEvent.click(screen.getByRole('button', { name: '修改密码' })); | |
await waitFor(() => { | |
expect(screen.getByText('原密码不正确')).toBeInTheDocument(); | |
}); | |
}); | |
it('应该显示加载状态', async () => { | |
// 延迟API响应以测试加载状态 | |
updatePassword.mockImplementation(() => new Promise(() => {})); | |
render( | |
<MemoryRouter> | |
<Setting /> | |
</MemoryRouter> | |
); | |
// 填写表单 | |
fireEvent.change(screen.getByLabelText('原密码:'), { | |
target: { value: 'oldpassword123' } | |
}); | |
fireEvent.change(screen.getByLabelText('新密码:'), { | |
target: { value: 'newpassword123' } | |
}); | |
fireEvent.change(screen.getByLabelText('确认新密码:'), { | |
target: { value: 'newpassword123' } | |
}); | |
// 提交表单 | |
fireEvent.click(screen.getByRole('button', { name: '修改密码' })); | |
// 检查加载状态 | |
expect(screen.getByText('处理中...')).toBeInTheDocument(); | |
expect(screen.getByRole('button', { name: '处理中...' })).toBeDisabled(); | |
}); | |
it('应该处理返回按钮点击', async () => { | |
render( | |
<MemoryRouter> | |
<Setting /> | |
</MemoryRouter> | |
); | |
const backButton = screen.getByText(/← 返回个人中心/); | |
fireEvent.click(backButton); | |
expect(mockNavigate).toHaveBeenCalledWith('/personal', { | |
state: { | |
fromSubpage: true, | |
dashboardTab: 'settings' | |
}, | |
replace: true | |
}); | |
}); | |
it('应该清空表单并显示成功消息', async () => { | |
render( | |
<MemoryRouter> | |
<Setting /> | |
</MemoryRouter> | |
); | |
// 填写表单 | |
fireEvent.change(screen.getByLabelText('原密码:'), { | |
target: { value: 'oldpassword123' } | |
}); | |
fireEvent.change(screen.getByLabelText('新密码:'), { | |
target: { value: 'newpassword123' } | |
}); | |
fireEvent.change(screen.getByLabelText('确认新密码:'), { | |
target: { value: 'newpassword123' } | |
}); | |
// 提交表单 | |
fireEvent.click(screen.getByRole('button', { name: '修改密码' })); | |
await waitFor(() => { | |
// 检查表单是否清空 | |
expect(screen.getByLabelText('原密码:')).toHaveValue(''); | |
expect(screen.getByLabelText('新密码:')).toHaveValue(''); | |
expect(screen.getByLabelText('确认新密码:')).toHaveValue(''); | |
// 检查成功消息 | |
expect(screen.getByText('密码修改成功')).toBeInTheDocument(); | |
}); | |
}); | |
}); |