|
@@ -0,0 +1,299 @@
|
|
|
|
|
+import { describe, it, expect, beforeEach } from 'vitest';
|
|
|
|
|
+import { testClient } from 'hono/testing';
|
|
|
|
|
+import {
|
|
|
|
|
+ IntegrationTestDatabase,
|
|
|
|
|
+ setupIntegrationDatabaseHooks,
|
|
|
|
|
+ TestDataFactory
|
|
|
|
|
+} from '~/utils/server/integration-test-db';
|
|
|
|
|
+import { adminOrdersRoutesExport } from '@d8d/server/api';
|
|
|
|
|
+import { AuthService } from '@d8d/server/modules/auth/auth.service';
|
|
|
|
|
+import { UserService } from '@d8d/server/modules/users/user.service';
|
|
|
|
|
+import { OrderStatus, PaymentStatus } from '@d8d/server/modules/orders/order.entity';
|
|
|
|
|
+
|
|
|
|
|
+// 设置集成测试钩子
|
|
|
|
|
+setupIntegrationDatabaseHooks()
|
|
|
|
|
+
|
|
|
|
|
+describe('订单管理API集成测试', () => {
|
|
|
|
|
+ let client: ReturnType<typeof testClient<typeof adminOrdersRoutesExport>>['api']['v1']['admin'];
|
|
|
|
|
+ let testToken: string;
|
|
|
|
|
+
|
|
|
|
|
+ beforeEach(async () => {
|
|
|
|
|
+ // 创建测试客户端
|
|
|
|
|
+ client = testClient(adminOrdersRoutesExport).api.v1.admin;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建测试用户并生成token
|
|
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
|
|
+
|
|
|
|
|
+ const userService = new UserService(dataSource);
|
|
|
|
|
+ const authService = new AuthService(userService);
|
|
|
|
|
+
|
|
|
|
|
+ // 确保admin用户存在
|
|
|
|
|
+ const user = await authService.ensureAdminExists();
|
|
|
|
|
+
|
|
|
|
|
+ // 生成admin用户的token
|
|
|
|
|
+ testToken = authService.generateToken(user);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('订单列表查询测试', () => {
|
|
|
|
|
+ it('应该成功获取订单列表', async () => {
|
|
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
|
|
+
|
|
|
|
|
+ // 创建测试数据
|
|
|
|
|
+ const testUser = await TestDataFactory.createTestUser(dataSource);
|
|
|
|
|
+ const testRoute = await TestDataFactory.createTestRoute(dataSource);
|
|
|
|
|
+
|
|
|
|
|
+ // 创建测试订单
|
|
|
|
|
+ await dataSource.getRepository('Order').save({
|
|
|
|
|
+ userId: testUser.id,
|
|
|
|
|
+ routeId: testRoute.id,
|
|
|
|
|
+ passengerCount: 2,
|
|
|
|
|
+ totalAmount: 100.00,
|
|
|
|
|
+ status: OrderStatus.PENDING_PAYMENT,
|
|
|
|
|
+ paymentStatus: PaymentStatus.PENDING,
|
|
|
|
|
+ passengerSnapshots: [
|
|
|
|
|
+ { name: '乘客1', phone: '13800138001' },
|
|
|
|
|
+ { name: '乘客2', phone: '13800138002' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ routeSnapshot: {
|
|
|
|
|
+ name: testRoute.name,
|
|
|
|
|
+ description: testRoute.description
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const response = await client.orders.$get({
|
|
|
|
|
+ query: {
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ pageSize: 10
|
|
|
|
|
+ }
|
|
|
|
|
+ }, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${testToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (response.status !== 200) {
|
|
|
|
|
+ const error = await response.json();
|
|
|
|
|
+ console.debug('Error response:', JSON.stringify(error, null, 2));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ expect(response.status).toBe(200);
|
|
|
|
|
+ if (response.status === 200) {
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ expect(Array.isArray(result.data)).toBe(true);
|
|
|
|
|
+ expect(result.pagination).toHaveProperty('total');
|
|
|
|
|
+ expect(result.pagination).toHaveProperty('current');
|
|
|
|
|
+ expect(result.pagination).toHaveProperty('pageSize');
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该支持按订单状态筛选', async () => {
|
|
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
|
|
+
|
|
|
|
|
+ // 创建测试数据
|
|
|
|
|
+ const testUser = await TestDataFactory.createTestUser(dataSource);
|
|
|
|
|
+ const testRoute = await TestDataFactory.createTestRoute(dataSource);
|
|
|
|
|
+
|
|
|
|
|
+ // 创建不同状态的测试订单
|
|
|
|
|
+ await dataSource.getRepository('Order').save([
|
|
|
|
|
+ {
|
|
|
|
|
+ userId: testUser.id,
|
|
|
|
|
+ routeId: testRoute.id,
|
|
|
|
|
+ passengerCount: 1,
|
|
|
|
|
+ totalAmount: 50.00,
|
|
|
|
|
+ status: OrderStatus.PENDING_PAYMENT,
|
|
|
|
|
+ paymentStatus: PaymentStatus.PENDING,
|
|
|
|
|
+ passengerSnapshots: [{ name: '乘客A', phone: '13800138003' }],
|
|
|
|
|
+ routeSnapshot: { name: testRoute.name }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ userId: testUser.id,
|
|
|
|
|
+ routeId: testRoute.id,
|
|
|
|
|
+ passengerCount: 3,
|
|
|
|
|
+ totalAmount: 150.00,
|
|
|
|
|
+ status: OrderStatus.COMPLETED,
|
|
|
|
|
+ paymentStatus: PaymentStatus.PAID,
|
|
|
|
|
+ passengerSnapshots: [
|
|
|
|
|
+ { name: '乘客B', phone: '13800138004' },
|
|
|
|
|
+ { name: '乘客C', phone: '13800138005' },
|
|
|
|
|
+ { name: '乘客D', phone: '13800138006' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ routeSnapshot: { name: testRoute.name }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ const response = await client.orders.$get({
|
|
|
|
|
+ query: {
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ filters: JSON.stringify({ status: OrderStatus.PENDING_PAYMENT })
|
|
|
|
|
+ }
|
|
|
|
|
+ }, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${testToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ expect(response.status).toBe(200);
|
|
|
|
|
+ if (response.status === 200) {
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ expect(result.data).toHaveLength(1);
|
|
|
|
|
+ expect(result.data[0].status).toBe(OrderStatus.PENDING_PAYMENT);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('订单详情查询测试', () => {
|
|
|
|
|
+ it('应该成功获取订单详情', async () => {
|
|
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
|
|
+
|
|
|
|
|
+ // 创建测试数据
|
|
|
|
|
+ const testUser = await TestDataFactory.createTestUser(dataSource);
|
|
|
|
|
+ const testRoute = await TestDataFactory.createTestRoute(dataSource);
|
|
|
|
|
+
|
|
|
|
|
+ // 创建测试订单
|
|
|
|
|
+ const order = await dataSource.getRepository('Order').save({
|
|
|
|
|
+ userId: testUser.id,
|
|
|
|
|
+ routeId: testRoute.id,
|
|
|
|
|
+ passengerCount: 2,
|
|
|
|
|
+ totalAmount: 100.00,
|
|
|
|
|
+ status: OrderStatus.PENDING_PAYMENT,
|
|
|
|
|
+ paymentStatus: PaymentStatus.PENDING,
|
|
|
|
|
+ passengerSnapshots: [
|
|
|
|
|
+ { name: '乘客1', phone: '13800138001' },
|
|
|
|
|
+ { name: '乘客2', phone: '13800138002' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ routeSnapshot: {
|
|
|
|
|
+ name: testRoute.name,
|
|
|
|
|
+ description: testRoute.description
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const response = await client.orders[':id'].$get({
|
|
|
|
|
+ param: { id: order.id }
|
|
|
|
|
+ }, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${testToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ expect(response.status).toBe(200);
|
|
|
|
|
+ if (response.status === 200) {
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ expect(result.id).toBe(order.id);
|
|
|
|
|
+ expect(result.userId).toBe(testUser.id);
|
|
|
|
|
+ expect(result.routeId).toBe(testRoute.id);
|
|
|
|
|
+ expect(result.passengerCount).toBe(2);
|
|
|
|
|
+ expect(result.totalAmount).toBe(100.00);
|
|
|
|
|
+ expect(result.status).toBe(OrderStatus.PENDING_PAYMENT);
|
|
|
|
|
+ expect(result.paymentStatus).toBe(PaymentStatus.PENDING);
|
|
|
|
|
+ expect(Array.isArray(result.passengerSnapshots)).toBe(true);
|
|
|
|
|
+ expect(result.passengerSnapshots).toHaveLength(2);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该返回404当订单不存在时', async () => {
|
|
|
|
|
+ const response = await client.orders[':id'].$get({
|
|
|
|
|
+ param: { id: 99999 }
|
|
|
|
|
+ }, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${testToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ expect(response.status).toBe(404);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('订单统计API测试', () => {
|
|
|
|
|
+ it('应该成功获取订单统计信息', async () => {
|
|
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
|
|
+
|
|
|
|
|
+ // 创建测试数据
|
|
|
|
|
+ const testUser = await TestDataFactory.createTestUser(dataSource);
|
|
|
|
|
+ const testRoute = await TestDataFactory.createTestRoute(dataSource);
|
|
|
|
|
+
|
|
|
|
|
+ // 创建不同状态的测试订单
|
|
|
|
|
+ await dataSource.getRepository('Order').save([
|
|
|
|
|
+ {
|
|
|
|
|
+ userId: testUser.id,
|
|
|
|
|
+ routeId: testRoute.id,
|
|
|
|
|
+ passengerCount: 1,
|
|
|
|
|
+ totalAmount: 50.00,
|
|
|
|
|
+ status: OrderStatus.PENDING_PAYMENT,
|
|
|
|
|
+ paymentStatus: PaymentStatus.PENDING,
|
|
|
|
|
+ passengerSnapshots: [{ name: '乘客A', phone: '13800138003' }],
|
|
|
|
|
+ routeSnapshot: { name: testRoute.name }
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ userId: testUser.id,
|
|
|
|
|
+ routeId: testRoute.id,
|
|
|
|
|
+ passengerCount: 2,
|
|
|
|
|
+ totalAmount: 100.00,
|
|
|
|
|
+ status: OrderStatus.COMPLETED,
|
|
|
|
|
+ paymentStatus: PaymentStatus.PAID,
|
|
|
|
|
+ passengerSnapshots: [
|
|
|
|
|
+ { name: '乘客B', phone: '13800138004' },
|
|
|
|
|
+ { name: '乘客C', phone: '13800138005' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ routeSnapshot: { name: testRoute.name }
|
|
|
|
|
+ }
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ const response = await client.orders.stats.$get({}, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${testToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ expect(response.status).toBe(200);
|
|
|
|
|
+ if (response.status === 200) {
|
|
|
|
|
+ const result = await response.json();
|
|
|
|
|
+ expect(result).toHaveProperty('total');
|
|
|
|
|
+ expect(result).toHaveProperty('pendingPayment');
|
|
|
|
|
+ expect(result).toHaveProperty('waitingDeparture');
|
|
|
|
|
+ expect(result).toHaveProperty('inProgress');
|
|
|
|
|
+ expect(result).toHaveProperty('completed');
|
|
|
|
|
+ expect(result).toHaveProperty('cancelled');
|
|
|
|
|
+
|
|
|
|
|
+ expect(result.total).toBeGreaterThanOrEqual(2);
|
|
|
|
|
+ expect(result.pendingPayment).toBeGreaterThanOrEqual(1);
|
|
|
|
|
+ expect(result.completed).toBeGreaterThanOrEqual(1);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ describe('权限控制测试', () => {
|
|
|
|
|
+ it('应该拒绝未授权访问', async () => {
|
|
|
|
|
+ const response = await client.orders.$get({
|
|
|
|
|
+ query: {
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ pageSize: 10
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ expect(response.status).toBe(401);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('应该拒绝非管理员访问', async () => {
|
|
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
|
|
+ const userService = new UserService(dataSource);
|
|
|
|
|
+ const authService = new AuthService(userService);
|
|
|
|
|
+
|
|
|
|
|
+ // 创建普通用户
|
|
|
|
|
+ const regularUser = await TestDataFactory.createTestUser(dataSource);
|
|
|
|
|
+ const regularToken = authService.generateToken(regularUser);
|
|
|
|
|
+
|
|
|
|
|
+ const response = await client.orders.$get({
|
|
|
|
|
+ query: {
|
|
|
|
|
+ page: 1,
|
|
|
|
|
+ pageSize: 10
|
|
|
|
|
+ }
|
|
|
|
|
+ }, {
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Authorization': `Bearer ${regularToken}`
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ expect(response.status).toBe(403);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+});
|