import { INestApplication } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import request from 'supertest'; import { afterAll, beforeAll, describe, expect, it } from 'vitest'; import { DataSource } from 'typeorm'; import { Channel } from './entities/channel.entity'; process.env.DB_HOST = '127.0.0.1'; process.env.DB_PORT = '3308'; process.env.DB_USER = 'fabric'; process.env.DB_PASSWORD = 'fabric'; process.env.DB_NAME = 'fabric_guild'; process.env.DB_SYNC = 'false'; process.env.FABRIC_API_KEY = 'test-api-key'; describe('guild integration (mysql + api)', () => { let app: INestApplication; let dataSource: DataSource; beforeAll(async () => { const { AppModule } = await import('./app.module'); const moduleRef = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleRef.createNestApplication(); app.setGlobalPrefix('api'); await app.init(); dataSource = app.get(DataSource); await dataSource.dropDatabase(); await dataSource.synchronize(); }, 30000); afterAll(async () => { if (app) await app.close(); }); it('GET /api/healthz returns db ready', async () => { const res = await request(app.getHttpServer()).get('/api/healthz'); expect(res.status).toBe(200); expect(res.body.ok).toBe(true); expect(res.body.service).toBe('guild'); }); it('protects non-health endpoints by x-api-key', async () => { const res = await request(app.getHttpServer()).get('/api/channels/non-exist/messages'); expect(res.status).toBe(401); }); it('supports concurrent message writes with continuous seq', async () => { const channelRepo = dataSource.getRepository(Channel); const channel = await channelRepo.save( channelRepo.create({ guildId: 'test-guild', name: `concurrency-${Date.now()}`, kind: 'text', isPrivate: false, lastSeq: 0, }), ); const concurrent = 10; const tasks = Array.from({ length: concurrent }, (_, i) => request(app.getHttpServer()) .post(`/api/channels/${channel.id}/messages`) .set('x-api-key', 'test-api-key') .send({ content: `hello-${i + 1}`, authorUserId: 'u1' }), ); const responses = await Promise.all(tasks); const seqs = responses.map((r) => r.body.seq).sort((a, b) => a - b); expect(responses.every((r) => r.status === 201)).toBe(true); expect(new Set(seqs).size).toBe(concurrent); expect(seqs).toEqual(Array.from({ length: concurrent }, (_, i) => i + 1)); }); });