import { describe, it, expect, beforeEach, vi } from 'vitest' // Taro.request mock(hoisted 保证 vi.mock 工厂能拿到同一引用) const mockRequest = vi.hoisted(() => vi.fn()) vi.mock('@tarojs/taro', () => ({ default: { request: mockRequest } })) const reLaunch = vi.hoisted(() => vi.fn()) vi.mock('@/utils/navigation', () => ({ reLaunch })) vi.mock('@/store', () => ({ store: { getState: () => ({ auth: { token: 'tk-test' } }), dispatch: vi.fn() } })) vi.mock('@/store/authSlice', () => ({ clearAuth: vi.fn() })) import { transferOwner } from '@/api/home' const okEnvelope = () => ({ statusCode: 200, data: { Code: '200', Message: '', Content: null }, header: {} }) beforeEach(() => { mockRequest.mockReset() reLaunch.mockReset() mockRequest.mockResolvedValue(okEnvelope()) }) describe('transferOwner', () => { it('POST /yanglao/app/ylHome/transferOwner 并把 { memberId } 作为请求体', async () => { await transferOwner({ memberId: 'm-target-001' }) expect(mockRequest).toHaveBeenCalledTimes(1) const arg = mockRequest.mock.calls[0][0] expect(arg.url).toMatch(/\/api\/biz\/yanglao\/app\/ylHome\/transferOwner$/) expect(arg.method).toBe('POST') expect(arg.data).toEqual({ memberId: 'm-target-001' }) // 自动注入 token(gateway / biz 前缀走业务网关) expect(arg.header.token).toBe('tk-test') }) it('业务码非 200 抛出 BusinessError(不踢登录)', async () => { mockRequest.mockResolvedValueOnce({ statusCode: 200, data: { Code: '500', Message: '无权操作', Content: null }, header: {} }) await expect(transferOwner({ memberId: 'm-2' })).rejects.toThrow('无权操作') expect(reLaunch).not.toHaveBeenCalled() }) it('业务码 202(未登录)触发踢回登录', async () => { mockRequest.mockResolvedValueOnce({ statusCode: 200, data: { Code: '202', Message: '未登录', Content: null }, header: {} }) await expect(transferOwner({ memberId: 'm-3' })).rejects.toThrow() expect(reLaunch).toHaveBeenCalled() }) })