87 lines
3.1 KiB
TypeScript
87 lines
3.1 KiB
TypeScript
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
||
|
||
// Taro.request 由各用例设置返回值(vi.hoisted 保证 mock 提升后仍可引用)
|
||
const mockRequest = vi.hoisted(() => vi.fn())
|
||
vi.mock('@tarojs/taro', () => ({ default: { request: mockRequest } }))
|
||
|
||
// client 依赖 store 取 token;此处只读,不触发 401 流程
|
||
vi.mock('@/store', () => ({
|
||
store: { getState: () => ({ auth: { token: 'unit-token' } }), dispatch: vi.fn() }
|
||
}))
|
||
|
||
import { request } from '@/http/client'
|
||
import { ApiError, BusinessError } from '@/http/errors'
|
||
|
||
const okBody = <T>(content: T) => ({
|
||
statusCode: 200,
|
||
data: { Code: '200', Message: '', Content: content, RecordCount: 0, PageIndex: 0, PageSize: 0 }
|
||
})
|
||
|
||
beforeEach(() => {
|
||
mockRequest.mockReset()
|
||
})
|
||
|
||
describe('client envelope 解析', () => {
|
||
it('Code=200 时解包返回 Content', async () => {
|
||
mockRequest.mockResolvedValue(okBody({ name: '张三' }))
|
||
const res = await request.get<{ name: string }>('/demo')
|
||
expect(res).toEqual({ name: '张三' })
|
||
// GET 参数经 data 透传(Taro 运行时序列化为 query string)
|
||
expect(mockRequest.mock.calls[0][0].data).toBeUndefined()
|
||
})
|
||
|
||
it('GET 参数放入 data 字段', async () => {
|
||
mockRequest.mockResolvedValue(okBody(null))
|
||
await request.get('/demo', { page: 1 })
|
||
expect(mockRequest.mock.calls[0][0].data).toEqual({ page: 1 })
|
||
})
|
||
|
||
it("Code='500' 抛 BusinessError(message + 字符串 code)", async () => {
|
||
mockRequest.mockResolvedValue({
|
||
statusCode: 200,
|
||
data: { Code: '500', Message: '手机号已绑定', Content: null }
|
||
})
|
||
await expect(request.get('/demo')).rejects.toMatchObject({
|
||
name: 'BusinessError',
|
||
message: '手机号已绑定',
|
||
code: '500'
|
||
})
|
||
await expect(request.get('/demo')).rejects.toBeInstanceOf(BusinessError)
|
||
})
|
||
|
||
it('HTTP 404 抛 ApiError 并带 statusCode', async () => {
|
||
mockRequest.mockResolvedValue({ statusCode: 404, data: 'Not Found' })
|
||
await expect(request.get('/demo')).rejects.toMatchObject({
|
||
name: 'ApiError',
|
||
message: 'HTTP 404',
|
||
statusCode: 404
|
||
})
|
||
})
|
||
|
||
it('Taro.request 异常(断网等)抛 ApiError', async () => {
|
||
mockRequest.mockRejectedValue(new Error('request:fail timeout'))
|
||
await expect(request.get('/demo')).rejects.toMatchObject({
|
||
name: 'ApiError',
|
||
message: 'request:fail timeout'
|
||
})
|
||
})
|
||
|
||
it('需鉴权请求注入 Bearer token 头', async () => {
|
||
mockRequest.mockResolvedValue(okBody(null))
|
||
await request.get('/demo')
|
||
expect(mockRequest.mock.calls[0][0].header.Authorization).toBe('Bearer unit-token')
|
||
})
|
||
|
||
it('needAuth: false 时不注入 Authorization', async () => {
|
||
mockRequest.mockResolvedValue(okBody(null))
|
||
await request.post('/demo', {}, { needAuth: false })
|
||
expect(mockRequest.mock.calls[0][0].header.Authorization).toBeUndefined()
|
||
})
|
||
|
||
it('BASE_URL 拼接:请求 url = BASE_URL + path', async () => {
|
||
mockRequest.mockResolvedValue(okBody(null))
|
||
await request.get('/thirdPlatform/wxDevLogin/miniapp/login')
|
||
expect(mockRequest.mock.calls[0][0].url).toMatch(/\/api\/biz\/thirdPlatform\/wxDevLogin\/miniapp\/login$/)
|
||
})
|
||
})
|