import { beforeEach, describe, expect, it, vi } from 'vitest'
const messageSuccessMock = vi.fn()
const messageErrorMock = vi.fn()
const isAxiosErrorMock = vi.fn((value: any) => Boolean(value?.isAxiosError))
vi.mock('element-plus', () => ({
ElMessage: {
success: messageSuccessMock,
error: messageErrorMock
}
}))
vi.mock('axios', () => ({
default: {
isAxiosError: isAxiosErrorMock
}
}))
vi.mock('../../../i18n', () => ({
i18n: {
global: {
t: (key: string) => `i18n:${key}`
}
}
}))
import { serverApi } from '../../../script/serverApi'
describe('serverApi', () => {
beforeEach(() => {
vi.clearAllMocks()
window.$t = ((key: string) => `t:${key}`) as any
})
it('未传 interface 时会走默认空实现并返回 null', async () => {
const loading = { isLoading: false }
await expect(serverApi({ loading })).resolves.toBeNull()
expect(loading.isLoading).toBe(false)
})
it('旧版成功响应会关闭 loading、触发 success,并在 tips=true 时提示成功', async () => {
const loading = { isLoading: false }
const success = vi.fn()
const api = vi.fn().mockResolvedValue({
status: 200,
data: {
list: [1, 2, 3]
}
})
await serverApi({
interface: api,
params: { page: 1 },
loading,
tips: true,
success
})
expect(api).toHaveBeenCalledWith({ page: 1 })
expect(loading.isLoading).toBe(false)
expect(success).toHaveBeenCalledWith({ list: [1, 2, 3] })
expect(messageSuccessMock).toHaveBeenCalledWith({ message: 'i18n:operationSuccess' })
})
it('新版成功响应默认把 response.data.content 传给 success', async () => {
const loading = { isLoading: false }
const success = vi.fn()
await serverApi({
interface: vi.fn().mockResolvedValue({
status: 200,
data: {
status: 0,
content: { id: 1, name: 'tom' }
}
}),
loading,
success
})
expect(loading.isLoading).toBe(false)
expect(success).toHaveBeenCalledWith({ id: 1, name: 'tom' })
})
it('returnResp=true 时 success 接收完整 response', async () => {
const loading = { isLoading: false }
const success = vi.fn()
const response = {
status: 200,
data: {
status: 0,
content: { id: 2 }
}
}
await serverApi({
interface: vi.fn().mockResolvedValue({ response }),
loading,
success,
returnResp: true
})
expect(success).toHaveBeenCalledWith(response)
})
it('interface 返回空值时会关闭 loading 并返回 null', async () => {
const loading = { isLoading: false }
await expect(
serverApi({
interface: vi.fn().mockResolvedValue(null),
loading
})
).resolves.toBeNull()
expect(loading.isLoading).toBe(false)
})
it('网络错误对象会走错误提示与 error 回调,并返回 null', async () => {
const loading = { isLoading: false }
const error = vi.fn()
const axiosError = {
isAxiosError: true,
code: 'ERR_NETWORK',
message: 'Network Error'
}
await expect(
serverApi({
interface: vi.fn().mockResolvedValue(axiosError),
loading,
error
})
).resolves.toBeNull()
expect(loading.isLoading).toBe(false)
expect(messageErrorMock).toHaveBeenCalledWith({
dangerouslyUseHTMLString: false,
message: 't:networkRequestError'
})
expect(error).toHaveBeenCalledWith(axiosError)
})
it('超时错误会提示 networkRequestTimeout', async () => {
const loading = { isLoading: false }
await serverApi({
interface: vi.fn().mockResolvedValue({
isAxiosError: true,
code: 'ETIMEDOUT',
message: 'timeout of 1000ms exceeded'
}),
loading,
error: vi.fn()
})
expect(messageErrorMock).toHaveBeenCalledWith({
dangerouslyUseHTMLString: false,
message: 't:networkRequestTimeout'
})
})
it('非 2xx 响应会走错误提示,并支持 html message', async () => {
const loading = { isLoading: false }
const error = vi.fn()
const response = {
status: 500,
data: {
message: 'line1
line2'
}
}
await serverApi({
interface: vi.fn().mockResolvedValue(response),
loading,
error
})
expect(loading.isLoading).toBe(false)
expect(messageErrorMock).toHaveBeenCalledWith({
dangerouslyUseHTMLString: true,
message: '