// REQ-USR-001 / REQ-USR-002: 用户单据 API 封装单测 // createUser / updateUser / getUserDetail / listEmployees / listPermissions 透传与归一(D1/D2/D4) import { describe, it, expect, vi, beforeEach } from 'vitest'; // 桩底层 axios 实例(request.ts 的 default 导出),沿用 usrApi.userlist.test.ts 模式 vi.mock('../../src/api/request', () => { return { default: { post: vi.fn(), put: vi.fn(), get: vi.fn(), }, }; }); import request from '../../src/api/request'; import { createUser, updateUser, getUserDetail, listEmployees, listPermissions, } from '../../src/api/usrApi'; const mockedRequest = request as unknown as { post: ReturnType; put: ReturnType; get: ReturnType; }; describe('usrApi 用户单据封装', () => { beforeEach(() => { vi.clearAllMocks(); }); it('createUser posts /usr/users with body (no password/creator/createDate)', async () => { mockedRequest.post.mockResolvedValue({ id: 9 }); const body = { sUserName: 'zhangsan', sUserNo: 'zs', iEmployeeId: 3, sUserType: '普通用户', sLanguage: '中文', iCanModifyBill: 0 as const, permissionIds: [1, 2], }; const ret = await createUser(body); expect(mockedRequest.post).toHaveBeenCalledTimes(1); const [url, payload] = mockedRequest.post.mock.calls[0]; expect(url).toBe('/usr/users'); expect(payload).toEqual(body); expect(payload).not.toHaveProperty('initialPassword'); expect(payload).not.toHaveProperty('sCreator'); expect(payload).not.toHaveProperty('tCreateDate'); expect(ret).toEqual({ id: 9 }); }); it('updateUser puts /usr/users/{id} with body (no sUserName)', async () => { mockedRequest.put.mockResolvedValue({ id: 7 }); const body = { sUserType: '超级管理员', sLanguage: '英文', iCanModifyBill: 1 as const, iIsVoid: 0 as const, permissionIds: [2], }; const ret = await updateUser(7, body); expect(mockedRequest.put).toHaveBeenCalledTimes(1); const [url, payload] = mockedRequest.put.mock.calls[0]; expect(url).toBe('/usr/users/7'); expect(payload).toEqual(body); expect(payload).not.toHaveProperty('sUserName'); expect(ret).toEqual({ id: 7 }); }); it('getUserDetail queries equals match pageSize 1 and returns records[0]', async () => { mockedRequest.get.mockResolvedValue({ records: [ { id: 7, sUserName: 'zhangsan', 员工名: '张三', sUserNo: 'zs', 部门: null, sUserType: '普通用户', sLanguage: '中文', iIsVoid: 0, tLastLoginDate: null, sCreator: 'admin', tCreateDate: '2026-01-01T00:00:00', }, ], total: 1, pageNum: 1, pageSize: 1, }); const ret = await getUserDetail({ queryField: '用户名', queryValue: 'zhangsan' }); expect(mockedRequest.get).toHaveBeenCalledTimes(1); const [url, config] = mockedRequest.get.mock.calls[0]; expect(url).toBe('/usr/users'); expect(config.params).toMatchObject({ queryField: '用户名', matchType: '等于', queryValue: 'zhangsan', pageNum: 1, pageSize: 1, }); expect(ret).not.toBeNull(); expect(ret!.id).toBe(7); expect(ret!.employeeName).toBe('张三'); }); it('getUserDetail returns null when records empty', async () => { mockedRequest.get.mockResolvedValue({ records: [], total: 0, pageNum: 1, pageSize: 1 }); const ret = await getUserDetail({ queryField: '用户名', queryValue: 'none' }); expect(ret).toBeNull(); }); it('listEmployees normalizes iIncrement/sEmployeeName/sEmployeeNo to EmployeeOption', async () => { mockedRequest.get.mockResolvedValue([ { iIncrement: 3, sEmployeeName: '张三', sEmployeeNo: 'zs' }, ]); const ret = await listEmployees(); expect(mockedRequest.get).toHaveBeenCalledWith('/usr/employees'); expect(ret).toEqual([{ value: 3, label: '张三', sEmployeeNo: 'zs' }]); }); it('listPermissions normalizes to PermissionItem', async () => { mockedRequest.get.mockResolvedValue([ { iIncrement: 1, sPermissionName: '默认显示', sPermissionCategory: '基础' }, ]); const ret = await listPermissions(); expect(mockedRequest.get).toHaveBeenCalledWith('/usr/permissions'); expect(ret).toEqual([{ id: 1, name: '默认显示', category: '基础' }]); }); });