import 'dotenv/config'; import { BadRequestException, ValidationPipe } from '@nestjs/common'; import type { INestApplication } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import { AppModule } from '../../../src/app.module.js'; import { WechatMiniAppService } from '../../../src/auth/wechat-miniapp/wechat-miniapp.service.js'; import { HttpExceptionFilter } from '../../../src/common/http-exception.filter.js'; import { MESSAGES } from '../../../src/common/messages.js'; import { ResponseEnvelopeInterceptor } from '../../../src/common/response-envelope.interceptor.js'; class FakeWechatMiniAppService { async resolvePhoneIdentity(loginCode: string, phoneCode: string) { return { openId: this.exchangeLoginCode(loginCode), phone: this.exchangePhoneCode(phoneCode), }; } exchangeLoginCode(loginCode: string) { return this.parseCode(loginCode, 'mock-login:'); } exchangePhoneCode(phoneCode: string) { return this.parseCode(phoneCode, 'mock-phone:'); } private parseCode(value: string, prefix: string) { if (typeof value !== 'string' || !value.startsWith(prefix)) { throw new Error(`invalid mock miniapp code: ${value}`); } return decodeURIComponent(value.slice(prefix.length)); } } export async function createE2eApp(): Promise { const moduleRef = await Test.createTestingModule({ imports: [AppModule], }) .overrideProvider(WechatMiniAppService) .useValue(new FakeWechatMiniAppService()) .compile(); const app = moduleRef.createNestApplication(); app.useGlobalPipes( new ValidationPipe({ whitelist: true, transform: true, forbidNonWhitelisted: true, exceptionFactory: (errors) => { const messages = errors .flatMap((error) => Object.values(error.constraints ?? {})) .filter((item): item is string => Boolean(item)); return new BadRequestException( messages.length > 0 ? messages.join(';') : MESSAGES.DEFAULT_BAD_REQUEST, ); }, }), ); app.useGlobalFilters(new HttpExceptionFilter()); app.useGlobalInterceptors(new ResponseEnvelopeInterceptor()); await app.init(); return app; }