feat: 完成sys模块迁移,对齐PHP/Java框架

- 重构sys模块架构,严格按admin/api/core分层
- 对齐所有sys实体与数据库表结构
- 实现完整的adminapi控制器,匹配PHP/Java契约
- 修复依赖注入问题,确保服务正确注册
- 添加自动迁移工具和契约验证
- 完善多租户支持和审计功能
- 统一命名规范,与PHP业务逻辑保持一致
This commit is contained in:
万物街
2025-09-21 21:29:28 +08:00
parent 2e361795d9
commit 127a4db1e3
839 changed files with 24932 additions and 57988 deletions

View File

@@ -0,0 +1,70 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { HealthzController } from '../src/core/health/healthzController';
import { HealthService } from '../src/core/health/healthService';
// 使用最小化测试应用,避免引入 AppModule 的外部依赖DB/Redis/Kafka 等)
describe('Health Endpoints (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
controllers: [HealthzController],
providers: [
{
provide: HealthService,
useValue: {
// 模拟健康检查,保证端点可用
check: jest.fn(async () => ({ status: 'ok' })),
detailedCheck: jest.fn(async () => [
{ name: 'database', status: 'up' },
{ name: 'queue', status: 'up' },
{ name: 'eventBus', status: 'up' },
{ name: 'cache', status: 'up' },
]),
checkDatabase: jest.fn(async () => ({ status: 'up' })),
},
},
],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
afterAll(async () => {
if (app) await app.close();
});
it('GET /healthz should be public and return 200 or 503 with JSON body', async () => {
const res = await request(app.getHttpServer()).get('/healthz');
expect([200, 503]).toContain(res.status);
expect(res.headers['content-type']).toMatch(/json/);
expect(res.body).toHaveProperty('status');
});
it('GET /readyz should be public and return 200 or 503 with JSON body', async () => {
const res = await request(app.getHttpServer()).get('/readyz');
expect([200, 503]).toContain(res.status);
expect(res.headers['content-type']).toMatch(/json/);
expect(res.body).toHaveProperty('status');
});
it('GET /health/livez alias should respond', async () => {
const res = await request(app.getHttpServer()).get('/health/livez');
expect([200, 503]).toContain(res.status);
});
it('GET /health/readyz alias should respond', async () => {
const res = await request(app.getHttpServer()).get('/health/readyz');
expect([200, 503]).toContain(res.status);
});
it('GET /startupz should be public and return 200 or 503 with JSON body', async () => {
const res = await request(app.getHttpServer()).get('/startupz');
expect([200, 503]).toContain(res.status);
expect(res.headers['content-type']).toMatch(/json/);
expect(res.body).toHaveProperty('status');
});
});