test: 添加前端 API 单元测试
- 添加 vitest 测试框架配置 - 添加 src/api/__tests__/api.test.ts: 16个 API 测试 - 修复 points.ts 和 ledger.ts 导入问题 测试覆盖: - AccountAPI: 物理账户和子账户方法 - TransactionAPI: transfer/deposit/withdraw - LedgerAPI: subjects/entry/accountEntries - ReconciliationAPI: 8个端点方法 - PointsAPI: 5个端点方法 - 类型定义和导出测试
This commit is contained in:
parent
4086cc00de
commit
4b78c43d42
10
package.json
10
package.json
@ -8,7 +8,10 @@
|
||||
"dev:mock": "VITE_USE_MOCK=true vite",
|
||||
"build": "vue-tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:coverage": "vitest run --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"vue": "^3.4.21",
|
||||
@ -25,7 +28,10 @@
|
||||
"vite": "^5.1.4",
|
||||
"vue-tsc": "^2.0.6",
|
||||
"msw": "^2.2.1",
|
||||
"@types/node": "^20.11.19"
|
||||
"@types/node": "^20.11.19",
|
||||
"vitest": "^1.3.1",
|
||||
"@vitest/coverage-v8": "^1.3.1",
|
||||
"happy-dom": "^13.6.2"
|
||||
},
|
||||
"msw": {
|
||||
"workerDirectory": [
|
||||
|
||||
183
src/api/__tests__/api.test.ts
Normal file
183
src/api/__tests__/api.test.ts
Normal file
@ -0,0 +1,183 @@
|
||||
/**
|
||||
* 前端 API 客户端单元测试
|
||||
* 测试所有 API 模块的方法定义和类型
|
||||
*/
|
||||
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
|
||||
// Mock axios
|
||||
vi.mock('axios', () => ({
|
||||
default: {
|
||||
create: vi.fn(() => ({
|
||||
interceptors: {
|
||||
request: { use: vi.fn() },
|
||||
response: { use: vi.fn() }
|
||||
},
|
||||
get: vi.fn(),
|
||||
post: vi.fn(),
|
||||
put: vi.fn(),
|
||||
delete: vi.fn()
|
||||
}))
|
||||
}
|
||||
}))
|
||||
|
||||
// ==================== Account API 测试 ====================
|
||||
describe('AccountAPI', () => {
|
||||
it('should export AccountAPI class', async () => {
|
||||
const { AccountAPI } = await import('../account')
|
||||
expect(AccountAPI).toBeDefined()
|
||||
})
|
||||
|
||||
it('should have physical account methods', async () => {
|
||||
const { AccountAPI } = await import('../account')
|
||||
|
||||
// 实体账户相关方法
|
||||
expect(typeof AccountAPI.createPhysicalAccount).toBe('function')
|
||||
expect(typeof AccountAPI.getPhysicalAccounts).toBe('function')
|
||||
expect(typeof AccountAPI.getPhysicalAccount).toBe('function')
|
||||
expect(typeof AccountAPI.freezePhysicalAccount).toBe('function')
|
||||
expect(typeof AccountAPI.unfreezePhysicalAccount).toBe('function')
|
||||
})
|
||||
|
||||
it('should have sub account methods', async () => {
|
||||
const { AccountAPI } = await import('../account')
|
||||
|
||||
// 虚拟子账户相关方法
|
||||
expect(typeof AccountAPI.createSubAccount).toBe('function')
|
||||
expect(typeof AccountAPI.getSubAccount).toBe('function')
|
||||
expect(typeof AccountAPI.getSubAccountBalance).toBe('function')
|
||||
expect(typeof AccountAPI.freezeSubAccount).toBe('function')
|
||||
expect(typeof AccountAPI.unfreezeSubAccount).toBe('function')
|
||||
expect(typeof AccountAPI.closeSubAccount).toBe('function')
|
||||
})
|
||||
})
|
||||
|
||||
// ==================== Transaction API 测试 ====================
|
||||
describe('TransactionAPI', () => {
|
||||
it('should export TransactionAPI class', async () => {
|
||||
const { TransactionAPI } = await import('../transaction')
|
||||
expect(TransactionAPI).toBeDefined()
|
||||
})
|
||||
|
||||
it('should have all required methods', async () => {
|
||||
const { TransactionAPI } = await import('../transaction')
|
||||
|
||||
// 5 个核心交易 API 方法
|
||||
expect(typeof TransactionAPI.transfer).toBe('function')
|
||||
expect(typeof TransactionAPI.deposit).toBe('function')
|
||||
expect(typeof TransactionAPI.withdraw).toBe('function')
|
||||
expect(typeof TransactionAPI.getTransaction).toBe('function')
|
||||
expect(typeof TransactionAPI.getTransactions).toBe('function')
|
||||
})
|
||||
|
||||
it('should have DepositRequest and WithdrawRequest types', async () => {
|
||||
// 类型检查 - 如果编译通过则测试通过
|
||||
const { TransactionAPI } = await import('../transaction')
|
||||
expect(TransactionAPI.deposit).toBeDefined()
|
||||
expect(TransactionAPI.withdraw).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
// ==================== Ledger API 测试 ====================
|
||||
describe('LedgerAPI', () => {
|
||||
it('should export LedgerAPI class', async () => {
|
||||
const { LedgerAPI } = await import('../ledger')
|
||||
expect(LedgerAPI).toBeDefined()
|
||||
})
|
||||
|
||||
it('should have all required methods', async () => {
|
||||
const { LedgerAPI } = await import('../ledger')
|
||||
|
||||
// 3 个账务 API 方法
|
||||
expect(typeof LedgerAPI.getSubjects).toBe('function')
|
||||
expect(typeof LedgerAPI.getEntry).toBe('function')
|
||||
expect(typeof LedgerAPI.getAccountEntries).toBe('function')
|
||||
})
|
||||
})
|
||||
|
||||
// ==================== Reconciliation API 测试 ====================
|
||||
describe('ReconciliationAPI', () => {
|
||||
it('should export ReconciliationAPI class', async () => {
|
||||
const { ReconciliationAPI } = await import('../reconciliation')
|
||||
expect(ReconciliationAPI).toBeDefined()
|
||||
})
|
||||
|
||||
it('should have all required methods', async () => {
|
||||
const { ReconciliationAPI } = await import('../reconciliation')
|
||||
|
||||
// 8 个对账 API 方法
|
||||
expect(typeof ReconciliationAPI.runReconciliation).toBe('function')
|
||||
expect(typeof ReconciliationAPI.getBatch).toBe('function')
|
||||
expect(typeof ReconciliationAPI.getBatchItems).toBe('function')
|
||||
expect(typeof ReconciliationAPI.verifyThreeAccounts).toBe('function')
|
||||
expect(typeof ReconciliationAPI.createAdjustment).toBe('function')
|
||||
expect(typeof ReconciliationAPI.approveAdjustment).toBe('function')
|
||||
expect(typeof ReconciliationAPI.rejectAdjustment).toBe('function')
|
||||
expect(typeof ReconciliationAPI.getPendingAdjustments).toBe('function')
|
||||
})
|
||||
|
||||
it('should export status label mappings', async () => {
|
||||
const {
|
||||
ReconciliationStatusLabels,
|
||||
ReconciliationItemStatusLabels,
|
||||
AdjustmentTypeLabels,
|
||||
AdjustmentStatusLabels
|
||||
} = await import('../reconciliation')
|
||||
|
||||
expect(ReconciliationStatusLabels).toBeDefined()
|
||||
expect(ReconciliationItemStatusLabels).toBeDefined()
|
||||
expect(AdjustmentTypeLabels).toBeDefined()
|
||||
expect(AdjustmentStatusLabels).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
// ==================== Points API 测试 ====================
|
||||
describe('PointsAPI', () => {
|
||||
it('should export PointsAPI class', async () => {
|
||||
const { PointsAPI } = await import('../points')
|
||||
expect(PointsAPI).toBeDefined()
|
||||
})
|
||||
|
||||
it('should have all required methods', async () => {
|
||||
const { PointsAPI } = await import('../points')
|
||||
|
||||
// 5 个积分 API 方法
|
||||
expect(typeof PointsAPI.getAccounts).toBe('function')
|
||||
expect(typeof PointsAPI.earnPoints).toBe('function')
|
||||
expect(typeof PointsAPI.spendPoints).toBe('function')
|
||||
expect(typeof PointsAPI.transferPoints).toBe('function')
|
||||
expect(typeof PointsAPI.getTransactions).toBe('function')
|
||||
})
|
||||
})
|
||||
|
||||
// ==================== Types 测试 ====================
|
||||
describe('Type Definitions', () => {
|
||||
it('should export points types', async () => {
|
||||
const types = await import('@/types/points')
|
||||
expect(types.PointsTypeLabels).toBeDefined()
|
||||
expect(types.PointsTransactionTypeLabels).toBeDefined()
|
||||
})
|
||||
|
||||
it('should export ledger types', async () => {
|
||||
const types = await import('@/types/ledger')
|
||||
expect(types.SubjectCategoryLabels).toBeDefined()
|
||||
expect(types.DirectionLabels).toBeDefined()
|
||||
expect(types.EntryStatusLabels).toBeDefined()
|
||||
expect(types.PredefinedSubjects).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
// ==================== API Index 导出测试 ====================
|
||||
describe('API Index Exports', () => {
|
||||
it('should export all API modules from index', async () => {
|
||||
const api = await import('../index')
|
||||
|
||||
expect(api.AccountAPI).toBeDefined()
|
||||
expect(api.TransactionAPI).toBeDefined()
|
||||
expect(api.ReconciliationAPI).toBeDefined()
|
||||
expect(api.PointsAPI).toBeDefined()
|
||||
expect(api.LedgerAPI).toBeDefined()
|
||||
expect(api.apiClient).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
* 账务 API 客户端
|
||||
* 提供会计科目、分录查询等功能
|
||||
*/
|
||||
import apiClient from './client'
|
||||
import { apiClient } from './client'
|
||||
import type {
|
||||
AccountingSubject,
|
||||
LedgerEntry,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
* 积分 API 客户端
|
||||
* 提供积分账户管理、积分获取/消费/转移等功能
|
||||
*/
|
||||
import apiClient from './client'
|
||||
import { apiClient } from './client'
|
||||
import type {
|
||||
PointsAccount,
|
||||
PointsTransaction,
|
||||
|
||||
24
vitest.config.ts
Normal file
24
vitest.config.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { defineConfig } from 'vitest/config'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue()],
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'happy-dom',
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
coverage: {
|
||||
provider: 'v8',
|
||||
reporter: ['text', 'json', 'html'],
|
||||
include: ['src/**/*.ts'],
|
||||
exclude: ['src/**/*.d.ts', 'src/**/*.test.ts', 'src/mocks/**'],
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user