import { INestApplication } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { AccessMode, ToolStatus } from '@prisma/client'; import { randomUUID } from 'crypto'; import request from 'supertest'; import { AppModule } from '../src/app.module'; import { PrismaService } from '../src/prisma/prisma.service'; interface ToolDetailResponse { id: string; slug: string; name: string; description: string; accessMode: string; displayVersion: string | null; } describe('Tools detail by slug (e2e)', () => { let app: INestApplication; let prisma: PrismaService; let categoryId = ''; let toolId = ''; let toolSlug = ''; beforeAll(async () => { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); prisma = app.get(PrismaService); }); beforeEach(async () => { categoryId = `cat_${randomUUID().replace(/-/g, '')}`; toolId = `tool_${randomUUID().replace(/-/g, '')}`; toolSlug = `tool-${randomUUID().slice(0, 8)}`; await prisma.category.create({ data: { id: categoryId, name: `Category ${toolSlug}`, }, }); await prisma.tool.create({ data: { id: toolId, name: 'Slug Detail Tool', slug: toolSlug, categoryId, description: '# Manual\n\n## Install', accessMode: AccessMode.web, openUrl: 'https://example.com/tool', versionOverride: '2026.04', status: ToolStatus.published, updatedAt: '2026-04-11', }, }); }); afterEach(async () => { await prisma.tool.deleteMany({ where: { id: toolId, }, }); await prisma.category.deleteMany({ where: { id: categoryId, }, }); }); afterAll(async () => { await app.close(); }); function getHttpServer(): Parameters[0] { return app.getHttpServer() as Parameters[0]; } it('returns a published tool detail by slug', async () => { await request(getHttpServer()) .get(`/tools/slug/${toolSlug}`) .expect(200) .expect(({ body }: { body: ToolDetailResponse }) => { expect(body.id).toBe(toolId); expect(body.slug).toBe(toolSlug); expect(body.name).toBe('Slug Detail Tool'); expect(body.description).toContain('# Manual'); expect(body.accessMode).toBe(AccessMode.web); expect(body.displayVersion).toBe('2026.04'); }); }); it('returns 404 for an unknown slug', async () => { await request(getHttpServer()).get('/tools/slug/missing-tool').expect(404); }); it('returns none mode tool detail with displayVersion', async () => { const noneToolId = `tool_${randomUUID().replace(/-/g, '')}`; const noneToolSlug = `none-tool-${randomUUID().slice(0, 8)}`; await prisma.tool.create({ data: { id: noneToolId, name: 'Preview Tool', slug: noneToolSlug, categoryId, description: '# Preview\n\n即将上线', accessMode: 'none' as AccessMode, versionOverride: 'preview-1', status: ToolStatus.published, updatedAt: '2026-04-11', }, }); await request(getHttpServer()) .get(`/tools/slug/${noneToolSlug}`) .expect(200) .expect(({ body }: { body: ToolDetailResponse }) => { expect(body.id).toBe(noneToolId); expect(body.accessMode).toBe('none'); expect(body.displayVersion).toBe('preview-1'); }); await prisma.tool.deleteMany({ where: { id: noneToolId, }, }); }); });