| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- import { DataSource } from 'typeorm';
- import { beforeEach, afterEach } from 'vitest';
- import { UserEntity } from '@d8d/server/modules/users/user.entity';
- import { Role } from '@d8d/server/modules/users/role.entity';
- import { ActivityEntity } from '@d8d/server/modules/activities/activity.entity';
- import { RouteEntity } from '@d8d/server/modules/routes/route.entity';
- import { LocationEntity } from '@d8d/server/modules/locations/location.entity';
- import { AreaEntity } from '@d8d/server/modules/areas/area.entity';
- import { VehicleType } from '@d8d/server/modules/routes/route.schema';
- import { Passenger } from '@d8d/server/modules/passengers/passenger.entity';
- import { IdType } from '@d8d/server/modules/passengers/passenger.schema';
- import { Order } from '@d8d/server/modules/orders/order.entity';
- import { OrderStatus, PaymentStatus } from '@d8d/server/share/order.types';
- import { AppDataSource } from '@d8d/server/data-source';
- /**
- * 集成测试数据库工具类 - 使用真实PostgreSQL数据库
- */
- export class IntegrationTestDatabase {
- /**
- * 清理集成测试数据库
- */
- static async cleanup(): Promise<void> {
- if (AppDataSource.isInitialized) {
- await AppDataSource.destroy();
- }
- }
- /**
- * 获取当前数据源
- */
- static async getDataSource(): Promise<DataSource> {
- if(!AppDataSource.isInitialized) {
- await AppDataSource.initialize();
- }
- return AppDataSource
- }
- }
- /**
- * 测试数据工厂类
- */
- export class TestDataFactory {
- /**
- * 创建测试用户数据
- */
- static createUserData(overrides: Partial<UserEntity> = {}): Partial<UserEntity> {
- const timestamp = Date.now();
- return {
- username: `testuser_${timestamp}`,
- password: 'TestPassword123!',
- email: `test_${timestamp}@example.com`,
- phone: `138${timestamp.toString().slice(-8)}`,
- nickname: `Test User ${timestamp}`,
- name: `Test Name ${timestamp}`,
- isDisabled: 0,
- isDeleted: 0,
- ...overrides
- };
- }
- /**
- * 创建测试角色数据
- */
- static createRoleData(overrides: Partial<Role> = {}): Partial<Role> {
- const timestamp = Date.now();
- return {
- name: `test_role_${timestamp}`,
- description: `Test role description ${timestamp}`,
- ...overrides
- };
- }
- /**
- * 创建测试区域数据
- */
- static createAreaData(overrides: Partial<AreaEntity> = {}): Partial<AreaEntity> {
- const timestamp = Date.now();
- return {
- name: `测试区域_${timestamp}`,
- code: `area_${timestamp}`,
- level: 1,
- parentId: null,
- isDisabled: 0,
- isDeleted: 0,
- ...overrides
- };
- }
- /**
- * 创建测试地点数据
- */
- static createLocationData(overrides: Partial<LocationEntity> = {}): Partial<LocationEntity> {
- const timestamp = Date.now();
- return {
- name: `北京测试地点_${timestamp}`,
- address: `北京市测试地址_${timestamp}`,
- provinceId: 0, // 将在创建时自动设置
- cityId: 0, // 将在创建时自动设置
- districtId: 0, // 将在创建时自动设置
- latitude: 39.9042,
- longitude: 116.4074,
- isDisabled: 0,
- isDeleted: 0,
- ...overrides
- };
- }
- /**
- * 在数据库中创建测试用户
- */
- static async createTestUser(dataSource: DataSource, overrides: Partial<UserEntity> = {}): Promise<UserEntity> {
- const userData = this.createUserData(overrides);
- const userRepository = dataSource.getRepository(UserEntity);
- const user = userRepository.create(userData);
- return await userRepository.save(user);
- }
- /**
- * 在数据库中创建测试角色
- */
- static async createTestRole(dataSource: DataSource, overrides: Partial<Role> = {}): Promise<Role> {
- const roleData = this.createRoleData(overrides);
- const roleRepository = dataSource.getRepository(Role);
- const role = roleRepository.create(roleData);
- return await roleRepository.save(role);
- }
- /**
- * 在数据库中创建测试区域
- */
- static async createTestArea(dataSource: DataSource, overrides: Partial<AreaEntity> = {}): Promise<AreaEntity> {
- const areaData = this.createAreaData(overrides);
- const areaRepository = dataSource.getRepository(AreaEntity);
- // 对于顶级区域(省/直辖市),parentId应该为null
- if (areaData.level === 1) {
- areaData.parentId = null;
- }
- // 对于市级区域,确保有对应的省级区域
- else if (areaData.level === 2 && !areaData.parentId) {
- const province = await this.createTestArea(dataSource, { level: 1 });
- areaData.parentId = province.id;
- }
- // 对于区县级区域,确保有对应的市级区域
- else if (areaData.level === 3 && !areaData.parentId) {
- const city = await this.createTestArea(dataSource, { level: 2 });
- areaData.parentId = city.id;
- }
- const area = areaRepository.create(areaData);
- return await areaRepository.save(area);
- }
- /**
- * 在数据库中创建测试地点
- */
- static async createTestLocation(dataSource: DataSource, overrides: Partial<LocationEntity> = {}): Promise<LocationEntity> {
- const locationData = this.createLocationData(overrides);
- const locationRepository = dataSource.getRepository(LocationEntity);
- // 确保关联的区域存在 - 按层级顺序创建
- if (!locationData.provinceId) {
- const province = await this.createTestArea(dataSource, { level: 1 });
- locationData.provinceId = province.id;
- }
- if (!locationData.cityId) {
- const city = await this.createTestArea(dataSource, { level: 2, parentId: locationData.provinceId });
- locationData.cityId = city.id;
- }
- if (!locationData.districtId) {
- const district = await this.createTestArea(dataSource, { level: 3, parentId: locationData.cityId });
- locationData.districtId = district.id;
- }
- const location = locationRepository.create(locationData);
- return await locationRepository.save(location);
- }
- /**
- * 创建测试活动数据
- */
- static createActivityData(overrides: Partial<ActivityEntity> = {}): Partial<ActivityEntity> {
- const timestamp = Date.now();
- const now = new Date();
- const tomorrow = new Date(now.getTime() + 24 * 60 * 60 * 1000);
- return {
- name: `测试活动_${timestamp}`,
- description: `测试活动描述_${timestamp}`,
- startDate: now,
- endDate: tomorrow,
- venueLocationId: 0, // 将在创建时自动设置
- isDisabled: 0,
- isDeleted: 0,
- ...overrides
- };
- }
- /**
- * 创建测试路线数据
- */
- static createRouteData(overrides: Partial<RouteEntity> = {}): Partial<RouteEntity> {
- const timestamp = Date.now();
- const now = new Date();
- const departureTime = new Date(now.getTime() + 2 * 60 * 60 * 1000); // 2小时后
- return {
- name: `测试路线_${timestamp}`,
- startLocationId: 0, // 将在创建时自动设置
- endLocationId: 0, // 将在创建时自动设置
- pickupPoint: `上车点_${timestamp}`,
- dropoffPoint: `下车点_${timestamp}`,
- departureTime: departureTime,
- vehicleType: VehicleType.BUS,
- price: 100,
- seatCount: 40,
- availableSeats: 40,
- isDisabled: 0,
- isDeleted: 0,
- ...overrides
- };
- }
- /**
- * 在数据库中创建测试活动
- */
- static async createTestActivity(dataSource: DataSource, overrides: Partial<ActivityEntity> = {}): Promise<ActivityEntity> {
- const activityData = this.createActivityData(overrides);
- const activityRepository = dataSource.getRepository(ActivityEntity);
- // 如果没有提供venueLocationId,自动创建一个测试地点
- if (!activityData.venueLocationId || activityData.venueLocationId === 0) {
- const testLocation = await this.createTestLocation(dataSource);
- activityData.venueLocationId = testLocation.id;
- }
- const activity = activityRepository.create(activityData);
- return await activityRepository.save(activity);
- }
- /**
- * 在数据库中创建测试路线
- */
- static async createTestRoute(dataSource: DataSource, overrides: Partial<RouteEntity> = {}): Promise<RouteEntity> {
- const routeData = this.createRouteData(overrides);
- const routeRepository = dataSource.getRepository(RouteEntity);
- // 如果没有提供startLocationId,自动创建一个测试地点
- if (!routeData.startLocationId || routeData.startLocationId === 0) {
- const startLocation = await this.createTestLocation(dataSource);
- routeData.startLocationId = startLocation.id;
- }
- // 如果没有提供endLocationId,自动创建一个测试地点
- if (!routeData.endLocationId || routeData.endLocationId === 0) {
- const endLocation = await this.createTestLocation(dataSource);
- routeData.endLocationId = endLocation.id;
- }
- // 如果没有提供activityId,自动创建一个测试活动
- if (!routeData.activityId) {
- const testActivity = await this.createTestActivity(dataSource);
- routeData.activityId = testActivity.id;
- }
- const route = routeRepository.create(routeData);
- return await routeRepository.save(route);
- }
- /**
- * 创建测试乘客数据
- */
- static createPassengerData(overrides: Partial<Passenger> = {}): Partial<Passenger> {
- const timestamp = Date.now();
- return {
- name: `测试乘客_${timestamp}`,
- idType: IdType.ID_CARD,
- idNumber: `11010119900101${timestamp.toString().slice(-4)}`,
- phone: `138${timestamp.toString().slice(-8)}`,
- isDefault: false,
- ...overrides
- };
- }
- /**
- * 在数据库中创建测试乘客
- */
- static async createTestPassenger(dataSource: DataSource, overrides: Partial<Passenger> = {}): Promise<Passenger> {
- const passengerData = this.createPassengerData(overrides);
- const passengerRepository = dataSource.getRepository(Passenger);
- // 如果没有提供userId,自动创建一个测试用户
- if (!passengerData.userId) {
- const testUser = await this.createTestUser(dataSource);
- passengerData.userId = testUser.id;
- }
- const passenger = passengerRepository.create(passengerData);
- return await passengerRepository.save(passenger);
- }
- /**
- * 创建测试订单数据
- */
- static createOrderData(overrides: Partial<Order> = {}): Partial<Order> {
- const timestamp = Date.now();
- return {
- userId: 0, // 将在创建时自动设置
- routeId: 0, // 将在创建时自动设置
- passengerCount: 2,
- totalAmount: 200.00,
- status: OrderStatus.PENDING_PAYMENT,
- paymentStatus: PaymentStatus.PENDING,
- passengerSnapshots: [
- { name: '测试乘客1', idType: '身份证', idNumber: '110101199001011234' },
- { name: '测试乘客2', idType: '身份证', idNumber: '110101199001011235' }
- ],
- routeSnapshot: {
- name: '测试路线快照',
- description: '测试路线描述',
- price: 100.00,
- departureTime: new Date(Date.now() + 24 * 60 * 60 * 1000)
- },
- ...overrides
- };
- }
- /**
- * 在数据库中创建测试订单
- */
- static async createTestOrder(dataSource: DataSource, overrides: Partial<Order> = {}): Promise<Order> {
- const orderData = this.createOrderData(overrides);
- const orderRepository = dataSource.getRepository(Order);
- // 如果没有提供userId,自动创建一个测试用户
- if (!orderData.userId || orderData.userId === 0) {
- const testUser = await this.createTestUser(dataSource);
- orderData.userId = testUser.id;
- }
- // 如果没有提供routeId,自动创建一个测试路线
- if (!orderData.routeId || orderData.routeId === 0) {
- const testRoute = await this.createTestRoute(dataSource);
- orderData.routeId = testRoute.id;
- }
- const order = orderRepository.create(orderData);
- return await orderRepository.save(order);
- }
- }
- /**
- * 集成测试数据库生命周期钩子
- */
- export function setupIntegrationDatabaseHooks() {
- beforeEach(async () => {
- await IntegrationTestDatabase.getDataSource();
- });
- afterEach(async () => {
- await IntegrationTestDatabase.cleanup();
- });
- }
|