|
|
@@ -75,12 +75,12 @@ const TestWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
|
);
|
|
|
};
|
|
|
|
|
|
-describe('AreaManagement Integration Tests', () => {
|
|
|
+describe('区域管理集成测试', () => {
|
|
|
beforeEach(() => {
|
|
|
vi.clearAllMocks();
|
|
|
});
|
|
|
|
|
|
- it('should render area management component with title', async () => {
|
|
|
+ it('应该渲染区域管理组件并显示标题', async () => {
|
|
|
// Mock successful API response for province data
|
|
|
(areaClient.index.$get as any).mockResolvedValueOnce(createMockResponse(200, {
|
|
|
data: [
|
|
|
@@ -112,7 +112,7 @@ describe('AreaManagement Integration Tests', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should show loading state when fetching data', async () => {
|
|
|
+ it('应该在获取数据时显示加载状态', async () => {
|
|
|
// Mock delayed API response
|
|
|
(areaClient.index.$get as any).mockImplementationOnce(() =>
|
|
|
new Promise(resolve => setTimeout(() => resolve(createMockResponse(200, { data: [] })), 100))
|
|
|
@@ -133,7 +133,7 @@ describe('AreaManagement Integration Tests', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should show empty state when no data', async () => {
|
|
|
+ it('应该在无数据时显示空状态', async () => {
|
|
|
// Mock empty API response
|
|
|
(areaClient.index.$get as any).mockResolvedValueOnce(createMockResponse(200, { data: [] }));
|
|
|
|
|
|
@@ -149,7 +149,7 @@ describe('AreaManagement Integration Tests', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should open create dialog when clicking add button', async () => {
|
|
|
+ it('应该在点击新增按钮时打开创建对话框', async () => {
|
|
|
// Mock successful API response
|
|
|
(areaClient.index.$get as any).mockResolvedValueOnce(createMockResponse(200, {
|
|
|
data: [
|
|
|
@@ -187,7 +187,7 @@ describe('AreaManagement Integration Tests', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should handle API errors gracefully', async () => {
|
|
|
+ it('应该优雅地处理API错误', async () => {
|
|
|
// Mock API error
|
|
|
(areaClient.index.$get as any).mockRejectedValueOnce(new Error('API Error'));
|
|
|
|
|
|
@@ -204,7 +204,7 @@ describe('AreaManagement Integration Tests', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should complete create and delete workflow', async () => {
|
|
|
+ it('应该完成创建和删除工作流程', async () => {
|
|
|
const { toast } = await import('sonner');
|
|
|
|
|
|
// Mock initial areas data
|
|
|
@@ -298,7 +298,7 @@ describe('AreaManagement Integration Tests', () => {
|
|
|
});
|
|
|
});
|
|
|
|
|
|
- it('should handle API errors in CRUD operations', async () => {
|
|
|
+ it('应该处理CRUD操作中的API错误', async () => {
|
|
|
const { areaClient } = await import('../../src/api/areaClient');
|
|
|
const { toast } = await import('sonner');
|
|
|
|
|
|
@@ -354,4 +354,250 @@ describe('AreaManagement Integration Tests', () => {
|
|
|
expect(toast.error).toHaveBeenCalledWith('创建失败,请重试');
|
|
|
});
|
|
|
});
|
|
|
+
|
|
|
+ it('应该支持4级区域层级(省→市→区→乡镇)', async () => {
|
|
|
+ // Mock initial data with all levels
|
|
|
+ const mockAreas = {
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ tenantId: 1,
|
|
|
+ name: '北京市',
|
|
|
+ code: '110000',
|
|
|
+ level: 1,
|
|
|
+ parentId: null,
|
|
|
+ isDisabled: 0
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 2,
|
|
|
+ tenantId: 1,
|
|
|
+ name: '北京市市辖区',
|
|
|
+ code: '110100',
|
|
|
+ level: 2,
|
|
|
+ parentId: 1,
|
|
|
+ isDisabled: 0
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 3,
|
|
|
+ tenantId: 1,
|
|
|
+ name: '朝阳区',
|
|
|
+ code: '110105',
|
|
|
+ level: 3,
|
|
|
+ parentId: 2,
|
|
|
+ isDisabled: 0
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 4,
|
|
|
+ tenantId: 1,
|
|
|
+ name: '建国门街道',
|
|
|
+ code: '110105001',
|
|
|
+ level: 4,
|
|
|
+ parentId: 3,
|
|
|
+ isDisabled: 0
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ };
|
|
|
+
|
|
|
+ (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));
|
|
|
+
|
|
|
+ render(
|
|
|
+ <TestWrapper>
|
|
|
+ <AreaManagement />
|
|
|
+ </TestWrapper>
|
|
|
+ );
|
|
|
+
|
|
|
+ // Wait for all level data to load
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByText('北京市')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('北京市市辖区')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('朝阳区')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('建国门街道')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // Verify all levels are displayed correctly
|
|
|
+ expect(screen.getByText('北京市')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('北京市市辖区')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('朝阳区')).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('建国门街道')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该成功创建4级区域(乡镇)', async () => {
|
|
|
+ const { toast } = await import('sonner');
|
|
|
+
|
|
|
+ // Mock initial data with district
|
|
|
+ const mockAreas = {
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ id: 3,
|
|
|
+ tenantId: 1,
|
|
|
+ name: '朝阳区',
|
|
|
+ code: '110105',
|
|
|
+ level: 3,
|
|
|
+ parentId: 2,
|
|
|
+ isDisabled: 0
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ };
|
|
|
+
|
|
|
+ (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));
|
|
|
+
|
|
|
+ render(
|
|
|
+ <TestWrapper>
|
|
|
+ <AreaManagement />
|
|
|
+ </TestWrapper>
|
|
|
+ );
|
|
|
+
|
|
|
+ // Wait for data to load
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByText('朝阳区')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // Click add child button for district
|
|
|
+ const addChildButtons = screen.getAllByRole('button', { name: '新增乡镇' });
|
|
|
+ fireEvent.click(addChildButtons[0]);
|
|
|
+
|
|
|
+ // Check if town creation dialog opens
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByRole('heading', { name: '新增乡镇' })).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('在区县 "朝阳区" 下新增街道/乡镇')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // Fill town form
|
|
|
+ const nameInput = screen.getByPlaceholderText('输入区域名称');
|
|
|
+ const codeInput = screen.getByPlaceholderText('输入行政区划代码');
|
|
|
+
|
|
|
+ fireEvent.change(nameInput, { target: { value: '建国门街道' } });
|
|
|
+ fireEvent.change(codeInput, { target: { value: '110105001' } });
|
|
|
+
|
|
|
+ // Mock successful town creation
|
|
|
+ (areaClient.index.$post as any).mockResolvedValue(createMockResponse(201, { id: 4, name: '建国门街道' }));
|
|
|
+
|
|
|
+ const submitButton = screen.getByText('创建');
|
|
|
+ fireEvent.click(submitButton);
|
|
|
+
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(areaClient.index.$post).toHaveBeenCalledWith({
|
|
|
+ json: {
|
|
|
+ tenantId: 1,
|
|
|
+ name: '建国门街道',
|
|
|
+ code: '110105001',
|
|
|
+ level: 4,
|
|
|
+ parentId: 3,
|
|
|
+ isDisabled: 0
|
|
|
+ }
|
|
|
+ });
|
|
|
+ expect(toast.success).toHaveBeenCalledWith('省市区创建成功');
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该处理4级区域状态切换', async () => {
|
|
|
+ const { toast } = await import('sonner');
|
|
|
+
|
|
|
+ // Mock initial data with town
|
|
|
+ const mockAreas = {
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ id: 4,
|
|
|
+ tenantId: 1,
|
|
|
+ name: '建国门街道',
|
|
|
+ code: '110105001',
|
|
|
+ level: 4,
|
|
|
+ parentId: 3,
|
|
|
+ isDisabled: 0
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ };
|
|
|
+
|
|
|
+ (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));
|
|
|
+
|
|
|
+ render(
|
|
|
+ <TestWrapper>
|
|
|
+ <AreaManagement />
|
|
|
+ </TestWrapper>
|
|
|
+ );
|
|
|
+
|
|
|
+ // Wait for data to load
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByText('建国门街道')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // Click toggle status button for town
|
|
|
+ const toggleButtons = screen.getAllByRole('button', { name: '禁用' });
|
|
|
+ fireEvent.click(toggleButtons[0]);
|
|
|
+
|
|
|
+ // Check if status toggle dialog opens
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByRole('heading', { name: '禁用确认' })).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('确定要禁用省市区 "建国门街道" 吗?')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // Mock successful status toggle
|
|
|
+ (areaClient[':id'].$put as any).mockResolvedValue(createMockResponse(200));
|
|
|
+
|
|
|
+ const confirmButton = screen.getByRole('button', { name: '确认' });
|
|
|
+ fireEvent.click(confirmButton);
|
|
|
+
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(areaClient[':id'].$put).toHaveBeenCalledWith({
|
|
|
+ param: { id: 4 },
|
|
|
+ json: { isDisabled: 1 }
|
|
|
+ });
|
|
|
+ expect(toast.success).toHaveBeenCalledWith('省市区禁用成功');
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('应该成功删除4级区域(乡镇)', async () => {
|
|
|
+ const { toast } = await import('sonner');
|
|
|
+
|
|
|
+ // Mock initial data with town
|
|
|
+ const mockAreas = {
|
|
|
+ data: [
|
|
|
+ {
|
|
|
+ id: 4,
|
|
|
+ tenantId: 1,
|
|
|
+ name: '建国门街道',
|
|
|
+ code: '110105001',
|
|
|
+ level: 4,
|
|
|
+ parentId: 3,
|
|
|
+ isDisabled: 0
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ };
|
|
|
+
|
|
|
+ (areaClient.index.$get as any).mockResolvedValue(createMockResponse(200, mockAreas));
|
|
|
+
|
|
|
+ render(
|
|
|
+ <TestWrapper>
|
|
|
+ <AreaManagement />
|
|
|
+ </TestWrapper>
|
|
|
+ );
|
|
|
+
|
|
|
+ // Wait for data to load
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByText('建国门街道')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // Click delete button for town
|
|
|
+ const deleteButtons = screen.getAllByRole('button', { name: '删除' });
|
|
|
+ fireEvent.click(deleteButtons[0]);
|
|
|
+
|
|
|
+ // Check if delete confirmation dialog opens
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(screen.getByRole('heading', { name: '确认删除' })).toBeInTheDocument();
|
|
|
+ expect(screen.getByText('确定要删除省市区 "建国门街道" 吗?此操作不可恢复。')).toBeInTheDocument();
|
|
|
+ });
|
|
|
+
|
|
|
+ // Mock successful deletion
|
|
|
+ (areaClient[':id'].$delete as any).mockResolvedValue(createMockResponse(204));
|
|
|
+
|
|
|
+ const confirmDeleteButton = screen.getByRole('button', { name: '确认删除' });
|
|
|
+ fireEvent.click(confirmDeleteButton);
|
|
|
+
|
|
|
+ await waitFor(() => {
|
|
|
+ expect(areaClient[':id'].$delete).toHaveBeenCalledWith({
|
|
|
+ param: { id: 4 }
|
|
|
+ });
|
|
|
+ expect(toast.success).toHaveBeenCalledWith('省市区删除成功');
|
|
|
+ });
|
|
|
+ });
|
|
|
});
|