| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- import { INestApplication } from '@nestjs/common';
- import { JwtService } from '@nestjs/jwt';
- import { Test } from '@nestjs/testing';
- import * as request from 'supertest';
- import { configureApp } from '../src/app.setup';
- import { AppModule } from '../src/app.module';
- import { AiSimulationClient } from '../src/modules/simulations/ai-simulation.client';
- import { PrismaService } from '../src/prisma/prisma.service';
- describe('Simulations (e2e)', () => {
- let app: INestApplication;
- let jwtService: JwtService;
- let prisma: PrismaService;
- const execute = jest.fn();
- const getResult = jest.fn();
- async function signToken() {
- return jwtService.signAsync({
- sub: 1,
- stylistId: '1',
- email: 'stylist@example.com',
- username: 'Ogawa',
- });
- }
- beforeAll(async () => {
- execute.mockReset();
- getResult.mockReset();
- const moduleRef = await Test.createTestingModule({
- imports: [AppModule],
- })
- .overrideProvider(AiSimulationClient)
- .useValue({ execute, getResult })
- .compile();
- app = moduleRef.createNestApplication();
- configureApp(app);
- await app.init();
- jwtService = app.get(JwtService);
- prisma = app.get(PrismaService);
- });
- afterAll(async () => {
- await prisma.aiHairSimulationTask.deleteMany({
- where: {
- taskId: {
- startsWith: 'sim-e2e-task-',
- },
- },
- });
- await prisma.aiHairSimulation.deleteMany({
- where: {
- simulateRemark: {
- startsWith: 'sim-e2e-',
- },
- },
- });
- await prisma.hairTemplate.deleteMany({
- where: {
- templateName: {
- startsWith: 'sim-e2e-',
- },
- },
- });
- await prisma.customer.deleteMany({
- where: {
- name: {
- startsWith: 'sg-',
- },
- },
- });
- await app.close();
- });
- it('/api/v1/simulations (POST) creates an anonymous simulation', async () => {
- const token = await signToken();
- const uniqueSuffix = Date.now();
- const template = await prisma.hairTemplate.create({
- data: {
- templateName: `sim-e2e-template-${uniqueSuffix}`,
- coverUrl: '',
- status: 'PUBLIC',
- category: 'SHORT',
- tags: '',
- description: null,
- modelUrl: '',
- clothesUrl: '',
- backgroundUrl: '',
- refHairUrl: '',
- hairstylistId: BigInt(1),
- templateUrl: `https://cdn.example.com/${uniqueSuffix}.zip`,
- isSystemTemplate: 'NO',
- } as never,
- });
- execute.mockResolvedValueOnce({
- taskId: `sim-e2e-task-${uniqueSuffix}`,
- });
- const response = await request(app.getHttpServer())
- .post('/api/v1/simulations')
- .set('Authorization', `Bearer ${token}`)
- .send({
- originImage: 'https://cdn.example.com/origin.jpg',
- templateIds: [template.id.toString()],
- simulateRemark: `sim-e2e-${uniqueSuffix}`,
- });
- expect(response.status).toBe(201);
- expect(execute).toHaveBeenCalledWith(
- template.templateUrl,
- 'https://cdn.example.com/origin.jpg',
- );
- expect(response.body.data).toEqual({
- simulationId: expect.any(String),
- });
- });
- it('/api/v1/simulations/:id (GET) returns task detail for the owner', async () => {
- const token = await signToken();
- const uniqueSuffix = `${Date.now()}-detail`;
- const template = await prisma.hairTemplate.create({
- data: {
- templateName: `sim-e2e-template-${uniqueSuffix}`,
- coverUrl: 'https://cdn.example.com/cover.png',
- status: 'PUBLIC',
- category: 'MEDIUM',
- tags: 'airy',
- description: 'detail template',
- modelUrl: '',
- clothesUrl: '',
- backgroundUrl: '',
- refHairUrl: '',
- hairstylistId: BigInt(1),
- templateUrl: `https://cdn.example.com/${uniqueSuffix}.zip`,
- isSystemTemplate: 'NO',
- } as never,
- });
- execute.mockResolvedValueOnce({
- taskId: `sim-e2e-task-${uniqueSuffix}`,
- });
- const created = await request(app.getHttpServer())
- .post('/api/v1/simulations')
- .set('Authorization', `Bearer ${token}`)
- .send({
- originImage: 'https://cdn.example.com/origin-detail.jpg',
- templateIds: [template.id.toString()],
- simulateRemark: `sim-e2e-${uniqueSuffix}`,
- })
- .expect(201);
- const response = await request(app.getHttpServer())
- .get(`/api/v1/simulations/${created.body.data.simulationId}`)
- .set('Authorization', `Bearer ${token}`)
- .expect(200);
- expect(response.body.data).toMatchObject({
- id: created.body.data.simulationId,
- createdAt: expect.any(String),
- originImage: 'https://cdn.example.com/origin-detail.jpg',
- totalTaskCount: 1,
- processingTaskCount: 1,
- successTaskCount: 0,
- failedTaskCount: 0,
- overallStatus: 'PROCESSING',
- tasks: [
- expect.objectContaining({
- templateId: template.id.toString(),
- templateName: template.templateName,
- templateCategory: template.category,
- templateSource: 'STYLIST',
- taskStatus: 'PROCESSING',
- resultImages: [],
- }),
- ],
- });
- });
- it('/api/v1/simulations/customer/:customerId/gallery (GET) returns flattened result cards', async () => {
- const token = await signToken();
- const uniqueSuffix = `${Date.now()}-gallery`;
- const customer = await prisma.customer.create({
- data: {
- hairstylistId: BigInt(1),
- name: `sg-${Date.now()}`,
- namePronunciation: '',
- phone: `090-${String(Date.now()).slice(-4)}-3333`,
- email: '',
- avatar: 'https://cdn.example.com/customer.png',
- expectContact: 'LINE',
- planDate: new Date(),
- nextFollowDate: new Date(),
- } as never,
- });
- const template = await prisma.hairTemplate.create({
- data: {
- templateName: `sim-e2e-template-${uniqueSuffix}`,
- coverUrl: 'https://cdn.example.com/cover.png',
- status: 'PUBLIC',
- category: 'SHORT',
- tags: 'airy',
- description: 'gallery template',
- modelUrl: '',
- clothesUrl: '',
- backgroundUrl: '',
- refHairUrl: '',
- hairstylistId: BigInt(1),
- templateUrl: `https://cdn.example.com/${uniqueSuffix}.zip`,
- isSystemTemplate: 'NO',
- } as never,
- });
- execute.mockResolvedValueOnce({
- taskId: `sim-e2e-task-${uniqueSuffix}`,
- });
- const created = await request(app.getHttpServer())
- .post('/api/v1/simulations')
- .set('Authorization', `Bearer ${token}`)
- .send({
- customerId: customer.id.toString(),
- originImage: 'https://cdn.example.com/origin-gallery.jpg',
- templateIds: [template.id.toString()],
- simulateRemark: `sim-e2e-${uniqueSuffix}`,
- })
- .expect(201);
- await prisma.aiHairSimulationTask.updateMany({
- where: {
- simulationId: BigInt(created.body.data.simulationId),
- },
- data: {
- taskStatus: 'SUCCESSES',
- resultImages: JSON.stringify([
- 'https://cdn.example.com/gallery-2.png',
- 'https://cdn.example.com/gallery-1.png',
- ]),
- } as never,
- });
- const response = await request(app.getHttpServer())
- .get(`/api/v1/simulations/customer/${customer.id}/gallery`)
- .set('Authorization', `Bearer ${token}`);
- expect(response.status).toBe(200);
- expect(response.body.data.items).toEqual(
- expect.arrayContaining([
- expect.objectContaining({
- simulationId: created.body.data.simulationId,
- imageUrl: 'https://cdn.example.com/gallery-2.png',
- templateName: template.templateName,
- taskStatus: 'SUCCESSES',
- }),
- expect.objectContaining({
- simulationId: created.body.data.simulationId,
- imageUrl: 'https://cdn.example.com/gallery-1.png',
- templateName: template.templateName,
- taskStatus: 'SUCCESSES',
- }),
- ]),
- );
- });
- });
|