v4.3 安全修复+代码质量+测试体系+护城河验证

## 安全修复 (5项)
- CRITICAL JWT 硬编码 fallback(jwt.strategy / app.module / user.module)
- HIGH seed_admin.js MongoDB 凭据泄漏
- MEDIUM 邮箱验证码泄漏
- MEDIUM 支付订单查询 IDOR
- MEDIUM 管理后台 NoSQL 注入

## 代码质量 (14处)
- console.log→Logger(user.service.ts)
- as any 类型化(11处跨7个文件)
- Schema 联合类型修复(progress.schema)
- Module 依赖缺失修复(progress.module)

## 测试体系 (61项)
- 后端单元测试 Jest(43项):BenchmarkService/UserService/PaymentController
- 后端集成测试 Supertest(11项):API 认证/支付/进度/管理
- 前端单元测试 Vitest(7项):配置文件/API端点
- 浏览器自动化 Playwright(7项):API smoke test
- 覆盖率报告 + e2e 配置

## 护城河 P0-P5 启动验证通过 + 编译通过
This commit is contained in:
yuzhiran
2026-06-11 10:27:35 +08:00
parent 9276ab9028
commit e6b79ddb21
39 changed files with 4576 additions and 246 deletions
+51
View File
@@ -0,0 +1,51 @@
import { describe, it, expect } from 'vitest'
describe('APP_CONFIG', () => {
it('should have APP_NAME', async () => {
const { APP_CONFIG } = await import('./config')
expect(APP_CONFIG.APP_NAME).toBeTruthy()
})
it('should have storage keys', async () => {
const { APP_CONFIG } = await import('./config')
expect(APP_CONFIG.STORAGE_KEYS.TOKEN).toBe('token')
expect(APP_CONFIG.STORAGE_KEYS.USER_ID).toBe('userId')
})
it('should have page routes', async () => {
const { APP_CONFIG } = await import('./config')
expect(APP_CONFIG.PAGES.INDEX).toBe('/pages/index/index')
expect(APP_CONFIG.PAGES.LOGIN).toBe('/pages/login/login')
expect(APP_CONFIG.PAGES.MEMBER).toBe('/pages/member/member')
})
})
describe('API_ENDPOINTS', () => {
it('should have all endpoint groups', async () => {
const { API_ENDPOINTS } = await import('./config')
expect(API_ENDPOINTS.USER).toBeDefined()
expect(API_ENDPOINTS.INTERVIEW).toBeDefined()
expect(API_ENDPOINTS.PAYMENT).toBeDefined()
expect(API_ENDPOINTS.PROGRESS).toBeDefined()
expect(API_ENDPOINTS.CONTRIBUTION).toBeDefined()
expect(API_ENDPOINTS.MEMBER).toBeDefined()
})
it('should have user endpoints', async () => {
const { API_ENDPOINTS } = await import('./config')
expect(API_ENDPOINTS.USER.SEND_CODE).toBe('/user/send-code')
expect(API_ENDPOINTS.USER.LOGIN).toBe('/user/login')
expect(API_ENDPOINTS.USER.INFO).toBe('/user/info')
})
it('should generate dynamic interview endpoints', async () => {
const { API_ENDPOINTS } = await import('./config')
expect(API_ENDPOINTS.INTERVIEW.ANSWER('abc')).toBe('/interview/abc/answer')
expect(API_ENDPOINTS.INTERVIEW.GET('xyz')).toBe('/interview/xyz')
})
it('should generate dynamic payment check endpoint', async () => {
const { API_ENDPOINTS } = await import('./config')
expect(API_ENDPOINTS.PAYMENT.CHECK('ORD123')).toBe('/payment/check/ORD123')
})
})