|
|
@@ -1,309 +0,0 @@
|
|
|
-import { describe, it, expect, beforeEach } from 'vitest';
|
|
|
-import { testClient } from 'hono/testing';
|
|
|
-import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util';
|
|
|
-import { UserEntityMt, RoleMt } from '@d8d/core-module-mt/user-module-mt/entities';
|
|
|
-import { FileMt } from '@d8d/core-module-mt/file-module-mt/entities';
|
|
|
-import creditBalanceRoutes from '../../src/routes';
|
|
|
-import { CreditBalanceMt, CreditBalanceLogMt, CreditBalanceChangeType } from '../../src/entities';
|
|
|
-import { CreditBalanceTestDataFactory } from '../utils/test-data-factory';
|
|
|
-
|
|
|
-// 设置集成测试钩子
|
|
|
-setupIntegrationDatabaseHooksWithEntities([
|
|
|
- UserEntityMt, RoleMt, FileMt, CreditBalanceMt, CreditBalanceLogMt
|
|
|
-])
|
|
|
-
|
|
|
-describe('多租户信用额度API集成测试', () => {
|
|
|
- let client: ReturnType<typeof testClient<typeof creditBalanceRoutes>>;
|
|
|
- let userToken: string;
|
|
|
- let adminToken: string;
|
|
|
- let otherTenantUserToken: string;
|
|
|
- let testUser: UserEntityMt;
|
|
|
- let otherUser: UserEntityMt;
|
|
|
- let otherTenantUser: UserEntityMt;
|
|
|
-
|
|
|
- beforeEach(async () => {
|
|
|
- // 创建测试客户端
|
|
|
- client = testClient(creditBalanceRoutes);
|
|
|
-
|
|
|
- // 获取数据源并创建测试用户
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
-
|
|
|
- // 创建租户1的测试用户
|
|
|
- testUser = await CreditBalanceTestDataFactory.createTestUser(dataSource, 1);
|
|
|
- otherUser = await CreditBalanceTestDataFactory.createTestUser(dataSource, 1);
|
|
|
-
|
|
|
- // 创建租户2的测试用户
|
|
|
- otherTenantUser = await CreditBalanceTestDataFactory.createTestUser(dataSource, 2);
|
|
|
-
|
|
|
- // 生成JWT令牌
|
|
|
- userToken = CreditBalanceTestDataFactory.generateUserToken(testUser);
|
|
|
- adminToken = CreditBalanceTestDataFactory.generateAdminToken(1);
|
|
|
- otherTenantUserToken = CreditBalanceTestDataFactory.generateUserToken(otherTenantUser);
|
|
|
- });
|
|
|
-
|
|
|
- describe('查询用户信用额度', () => {
|
|
|
- it('应该返回404当用户信用额度记录不存在时', async () => {
|
|
|
- const response = await client[':userId'].$get({
|
|
|
- param: { userId: '9999' }
|
|
|
- }, {
|
|
|
- headers: {
|
|
|
- 'Authorization': `Bearer ${userToken}`
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- expect(response.status).toBe(404);
|
|
|
- if (response.status === 404) {
|
|
|
- const data = await response.json();
|
|
|
- expect(data.message).toBe('用户信用额度记录不存在');
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- it('应该返回用户的信用额度', async () => {
|
|
|
- // 先创建信用额度记录
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const creditBalanceRepo = dataSource.getRepository(CreditBalanceMt);
|
|
|
- await creditBalanceRepo.save({
|
|
|
- tenantId: 1,
|
|
|
- userId: testUser.id,
|
|
|
- totalLimit: 10000.00, // 明确使用小数形式
|
|
|
- usedAmount: 0.00,
|
|
|
- isEnabled: 1
|
|
|
- });
|
|
|
-
|
|
|
- const response = await client[':userId'].$get({
|
|
|
- param: { userId: testUser.id.toString() }
|
|
|
- }, {
|
|
|
- headers: {
|
|
|
- 'Authorization': `Bearer ${userToken}`
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- expect(response.status).toBe(200);
|
|
|
- if (response.status === 200) {
|
|
|
- const data = await response.json();
|
|
|
- expect(data.id).toBeDefined();
|
|
|
- expect(data.tenantId).toBe(1);
|
|
|
- expect(data.userId).toBe(testUser.id);
|
|
|
- expect(data.totalLimit).toBe(10000);
|
|
|
- expect(data.availableAmount).toBe(10000);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('设置用户信用额度', () => {
|
|
|
- it('应该成功设置用户信用额度', async () => {
|
|
|
- const response = await client[':userId'].$put({
|
|
|
- param: { userId: testUser.id.toString() },
|
|
|
- json: {
|
|
|
- totalLimit: 5000,
|
|
|
- operatorId: 1,
|
|
|
- remark: '初始设置额度'
|
|
|
- }
|
|
|
- }, {
|
|
|
- headers: {
|
|
|
- 'Authorization': `Bearer ${adminToken}`
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- expect(response.status).toBe(200);
|
|
|
- if (response.status === 200) {
|
|
|
- const data = await response.json();
|
|
|
- expect(data.totalLimit).toBe(5000);
|
|
|
- expect(data.availableAmount).toBe(5000);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('调整用户信用额度', () => {
|
|
|
- it('应该成功调整用户信用额度', async () => {
|
|
|
- // 先创建信用额度记录
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const creditBalanceRepo = dataSource.getRepository(CreditBalanceMt);
|
|
|
- await creditBalanceRepo.save({
|
|
|
- tenantId: 1,
|
|
|
- userId: testUser.id,
|
|
|
- totalLimit: 10000.00, // 明确使用小数形式
|
|
|
- usedAmount: 0.00,
|
|
|
- isEnabled: 1
|
|
|
- });
|
|
|
-
|
|
|
- const response = await client[':userId'].adjust.$post({
|
|
|
- param: { userId: testUser.id.toString() },
|
|
|
- json: {
|
|
|
- adjustAmount: 2000,
|
|
|
- operatorId: 1,
|
|
|
- remark: '增加额度'
|
|
|
- }
|
|
|
- }, {
|
|
|
- headers: {
|
|
|
- 'Authorization': `Bearer ${adminToken}`
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- expect(response.status).toBe(200);
|
|
|
- if (response.status === 200) {
|
|
|
- const data = await response.json();
|
|
|
- expect(data.totalLimit).toBeCloseTo(12000, 2); // 10000 + 2000,允许2位小数误差
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('额度支付', () => {
|
|
|
- it('应该成功扣减额度', async () => {
|
|
|
- // 先创建信用额度记录
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const creditBalanceRepo = dataSource.getRepository(CreditBalanceMt);
|
|
|
- await creditBalanceRepo.save({
|
|
|
- tenantId: 1,
|
|
|
- userId: testUser.id,
|
|
|
- totalLimit: 10000.00, // 明确使用小数形式
|
|
|
- usedAmount: 0.00,
|
|
|
- isEnabled: 1
|
|
|
- });
|
|
|
-
|
|
|
- const response = await client.payment.$post({
|
|
|
- json: {
|
|
|
- amount: 500.00,
|
|
|
- referenceId: 'ORD202412010001',
|
|
|
- operatorId: 1,
|
|
|
- remark: '订单支付'
|
|
|
- }
|
|
|
- }, {
|
|
|
- headers: {
|
|
|
- 'Authorization': `Bearer ${userToken}`
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- expect(response.status).toBe(200);
|
|
|
- if (response.status === 200) {
|
|
|
- const data = await response.json();
|
|
|
- expect(data.usedAmount).toBeCloseTo(500, 2);
|
|
|
- expect(data.availableAmount).toBeCloseTo(9500, 2); // 10000 - 500
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('结账恢复额度', () => {
|
|
|
- it('应该成功恢复额度', async () => {
|
|
|
- // 先创建信用额度记录并扣减
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const creditBalanceRepo = dataSource.getRepository(CreditBalanceMt);
|
|
|
- await creditBalanceRepo.save({
|
|
|
- tenantId: 1,
|
|
|
- userId: testUser.id,
|
|
|
- totalLimit: 10000,
|
|
|
- usedAmount: 500, // 已使用500
|
|
|
- isEnabled: 1
|
|
|
- });
|
|
|
-
|
|
|
- const response = await client.checkout.$post({
|
|
|
- json: {
|
|
|
- userId: testUser.id,
|
|
|
- amount: 300.00,
|
|
|
- referenceId: 'ORD202412010001',
|
|
|
- operatorId: 1,
|
|
|
- remark: '结账恢复'
|
|
|
- }
|
|
|
- }, {
|
|
|
- headers: {
|
|
|
- 'Authorization': `Bearer ${adminToken}`
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- expect(response.status).toBe(200);
|
|
|
- if (response.status === 200) {
|
|
|
- const data = await response.json();
|
|
|
- expect(data.usedAmount).toBe(200); // 500 - 300
|
|
|
- expect(data.availableAmount).toBe(9800); // 10000 - 200
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('查询额度变更记录', () => {
|
|
|
- it('应该返回额度变更记录', async () => {
|
|
|
- // 先创建信用额度记录和变更记录
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const creditBalanceRepo = dataSource.getRepository(CreditBalanceMt);
|
|
|
- const creditBalanceLogRepo = dataSource.getRepository(CreditBalanceLogMt);
|
|
|
-
|
|
|
- await creditBalanceRepo.save({
|
|
|
- tenantId: 1,
|
|
|
- userId: testUser.id,
|
|
|
- totalLimit: 10000,
|
|
|
- usedAmount: 500,
|
|
|
- isEnabled: 1
|
|
|
- });
|
|
|
-
|
|
|
- await creditBalanceLogRepo.save({
|
|
|
- tenantId: 1,
|
|
|
- userId: testUser.id,
|
|
|
- changeType: CreditBalanceChangeType.PAYMENT,
|
|
|
- changeAmount: -500,
|
|
|
- beforeTotal: 10000,
|
|
|
- afterTotal: 10000,
|
|
|
- beforeUsed: 0,
|
|
|
- afterUsed: 500,
|
|
|
- referenceId: 'ORD202412010001',
|
|
|
- operatorId: 1,
|
|
|
- remark: '订单支付'
|
|
|
- });
|
|
|
-
|
|
|
- const response = await client[':userId'].logs.$get({
|
|
|
- param: { userId: testUser.id.toString() },
|
|
|
- query: { page: 1, pageSize: 10 }
|
|
|
- }, {
|
|
|
- headers: {
|
|
|
- 'Authorization': `Bearer ${userToken}`
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- expect(response.status).toBe(200);
|
|
|
- if (response.status === 200) {
|
|
|
- const data = await response.json();
|
|
|
- expect(data.data).toHaveLength(1);
|
|
|
- expect(data.data[0].changeAmount).toBeCloseTo(-500, 2);
|
|
|
- expect(data.pagination.total).toBe(1);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- describe('租户数据隔离验证', () => {
|
|
|
- it('应该只能访问自己租户的信用额度', async () => {
|
|
|
- // 创建租户1的信用额度记录
|
|
|
- const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
- const creditBalanceRepo = dataSource.getRepository(CreditBalanceMt);
|
|
|
- await creditBalanceRepo.save({
|
|
|
- tenantId: 1,
|
|
|
- userId: testUser.id,
|
|
|
- totalLimit: 10000,
|
|
|
- usedAmount: 0,
|
|
|
- isEnabled: 1
|
|
|
- });
|
|
|
-
|
|
|
- // 创建租户2的信用额度记录
|
|
|
- await creditBalanceRepo.save({
|
|
|
- tenantId: 2,
|
|
|
- userId: otherTenantUser.id,
|
|
|
- totalLimit: 5000,
|
|
|
- usedAmount: 0,
|
|
|
- isEnabled: 1
|
|
|
- });
|
|
|
-
|
|
|
- // 使用租户1的用户查询
|
|
|
- const response = await client[':userId'].$get({
|
|
|
- param: { userId: testUser.id.toString() }
|
|
|
- }, {
|
|
|
- headers: {
|
|
|
- 'Authorization': `Bearer ${userToken}`
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- expect(response.status).toBe(200);
|
|
|
- if (response.status === 200) {
|
|
|
- const data = await response.json();
|
|
|
- expect(data.tenantId).toBe(1);
|
|
|
- expect(data.userId).toBe(testUser.id);
|
|
|
- }
|
|
|
- });
|
|
|
- });
|
|
|
-});
|