import React from 'react'
import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import Statistics from '../../src/pages/Statistics/Statistics'
// Mock Taro
jest.mock('@tarojs/taro', () => ({
createCanvasContext: jest.fn(() => ({
draw: jest.fn(),
stroke: jest.fn(),
beginPath: jest.fn(),
closePath: jest.fn(),
moveTo: jest.fn(),
lineTo: jest.fn(),
arc: jest.fn(),
setFillStyle: jest.fn(),
setStrokeStyle: jest.fn(),
setLineWidth: jest.fn(),
fillText: jest.fn(),
setTextAlign: jest.fn(),
setTextBaseline: jest.fn(),
fill: jest.fn(),
translate: jest.fn(),
rotate: jest.fn(),
scale: jest.fn(),
})),
getSystemInfoSync: jest.fn(() => ({
pixelRatio: 2,
windowWidth: 375,
windowHeight: 667,
})),
ENV_TYPE: {
WEAPP: 'WEAPP',
SWAN: 'SWAN',
ALIPAY: 'ALIPAY',
TT: 'TT',
QQ: 'QQ',
JD: 'JD',
},
getEnv: jest.fn(() => 'WEAPP'),
}))
// Mock React Query
jest.mock('@tanstack/react-query', () => ({
useQuery: jest.fn(() => ({
data: null,
isLoading: false,
error: null,
})),
}))
// Mock mini-charts components
jest.mock('@d8d/mini-charts', () => ({
ColumnChart: ({ canvasId, width, height }: any) => (
{canvasId} ({width}x{height})
),
PieChart: ({ canvasId, width, height, pieType }: any) => (
{canvasId} ({width}x{height}) {pieType}
),
BarChart: ({ canvasId, width, height }: any) => (
{canvasId} ({width}x{height})
),
}))
// Mock layout components
jest.mock('@d8d/yongren-shared-ui/components/YongrenTabBarLayout', () => ({
YongrenTabBarLayout: ({ children, activeKey }: any) => (
{children}
),
}))
jest.mock('@d8d/mini-shared-ui-components/components/navbar', () => ({
Navbar: ({ title }: any) => {title}
,
}))
// Mock API client
jest.mock('../../src/api/enterpriseStatisticsClient', () => ({
enterpriseStatisticsClient: {
'disability-type-distribution': {
$get: jest.fn(),
},
'gender-distribution': {
$get: jest.fn(),
},
'age-distribution': {
$get: jest.fn(),
},
'household-distribution': {
$get: jest.fn(),
},
'job-status-distribution': {
$get: jest.fn(),
},
'salary-distribution': {
$get: jest.fn(),
},
},
}))
describe('Statistics Page', () => {
beforeEach(() => {
jest.clearAllMocks()
})
it('应该正确渲染统计页面', () => {
render()
expect(screen.getByTestId('navbar')).toHaveTextContent('数据统计')
})
it('应该显示统计卡片', () => {
render()
expect(screen.getByText('在职人数')).toBeInTheDocument()
expect(screen.getByText('平均薪资')).toBeInTheDocument()
expect(screen.getByText('在职率')).toBeInTheDocument()
expect(screen.getByText('新增人数')).toBeInTheDocument()
})
it('应该显示所有图表标题', () => {
render()
expect(screen.getByText('残疾类型分布')).toBeInTheDocument()
expect(screen.getByText('性别分布')).toBeInTheDocument()
expect(screen.getByText('年龄分布')).toBeInTheDocument()
expect(screen.getByText('户籍省份分布')).toBeInTheDocument()
expect(screen.getByText('在职状态统计')).toBeInTheDocument()
expect(screen.getByText('薪资分布')).toBeInTheDocument()
})
it('应该渲染残疾类型柱状图', () => {
const { useQuery } = require('@tanstack/react-query')
useQuery.mockImplementation(() => ({
data: {
stats: [
{ key: '肢体', value: 10, percentage: 35.7 },
{ key: '听力', value: 8, percentage: 28.6 },
],
total: 28,
},
isLoading: false,
}))
render()
expect(screen.getByTestId('column-chart-disability-type-chart')).toBeInTheDocument()
})
it('应该渲染性别分布柱状图', () => {
const { useQuery } = require('@tanstack/react-query')
useQuery.mockImplementation(() => ({
data: {
stats: [
{ key: '男', value: 15, percentage: 60 },
{ key: '女', value: 10, percentage: 40 },
],
total: 25,
},
isLoading: false,
}))
render()
expect(screen.getByTestId('column-chart-gender-chart')).toBeInTheDocument()
})
it('应该渲染年龄分布饼图', () => {
const { useQuery } = require('@tanstack/react-query')
useQuery.mockImplementation(() => ({
data: {
stats: [
{ key: '18-25岁', value: 5, percentage: 20 },
{ key: '26-35岁', value: 10, percentage: 40 },
],
total: 25,
},
isLoading: false,
}))
render()
expect(screen.getByTestId('pie-chart-age-chart')).toBeInTheDocument()
expect(screen.getByTestId('pie-chart-age-chart')).toHaveAttribute('data-pie-type', 'pie')
})
it('应该渲染户籍省份横向柱状图', () => {
const { useQuery } = require('@tanstack/react-query')
useQuery.mockImplementation(() => ({
data: {
stats: [
{ key: '广东', value: 10, percentage: 40 },
{ key: '湖南', value: 8, percentage: 32 },
],
total: 25,
},
isLoading: false,
}))
render()
expect(screen.getByTestId('bar-chart-household-chart')).toBeInTheDocument()
})
it('应该渲染在职状态环形图', () => {
const { useQuery } = require('@tanstack/react-query')
useQuery.mockImplementation(() => ({
data: {
stats: [
{ key: '在职', value: 20, percentage: 80 },
{ key: '离职', value: 5, percentage: 20 },
],
total: 25,
},
isLoading: false,
}))
render()
expect(screen.getByTestId('pie-chart-job-status-chart')).toBeInTheDocument()
expect(screen.getByTestId('pie-chart-job-status-chart')).toHaveAttribute('data-pie-type', 'ring')
})
it('应该渲染薪资分布横向柱状图', () => {
const { useQuery } = require('@tanstack/react-query')
useQuery.mockImplementation(() => ({
data: {
stats: [
{ key: '3000-4000', value: 5, percentage: 20 },
{ key: '4000-5000', value: 10, percentage: 40 },
],
total: 25,
},
isLoading: false,
}))
render()
expect(screen.getByTestId('bar-chart-salary-chart')).toBeInTheDocument()
})
it('应该显示加载状态', () => {
const { useQuery } = require('@tanstack/react-query')
useQuery.mockImplementation(() => ({
data: null,
isLoading: true,
}))
render()
expect(screen.getAllByText('加载中...')).toHaveLength(6)
})
it('应该显示暂无数据状态', () => {
const { useQuery } = require('@tanstack/react-query')
useQuery.mockImplementation(() => ({
data: { stats: [], total: 0 },
isLoading: false,
}))
render()
expect(screen.getAllByText('暂无数据')).toHaveLength(6)
})
})
describe('数据转换函数', () => {
it('convertToColumnData 应该正确转换数据', () => {
const stats = [
{ key: '类别A', value: 10 },
{ key: '类别B', value: 20 },
]
const result = {
categories: ['类别A', '类别B'],
series: [{
name: '人数',
data: [10, 20]
}]
}
expect(result.categories).toEqual(['类别A', '类别B'])
expect(result.series[0].data).toEqual([10, 20])
})
it('convertToPieData 应该正确转换数据', () => {
const stats = [
{ key: '类别A', value: 10 },
{ key: '类别B', value: 20 },
]
const result = stats.map(item => ({
name: item.key,
data: item.value || 0
}))
expect(result).toEqual([
{ name: '类别A', data: 10 },
{ name: '类别B', data: 20 }
])
})
})