|
|
@@ -0,0 +1,326 @@
|
|
|
+import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
|
|
+import { testClient } from 'hono/testing';
|
|
|
+import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util';
|
|
|
+import { JWTUtil } from '@d8d/shared-utils';
|
|
|
+import { UserEntity, Role } from '@d8d/user-module';
|
|
|
+import { File } from '@d8d/file-module';
|
|
|
+import { tenantRoutes } from '../../src/routes';
|
|
|
+import { TenantEntityMt } from '../../src/entities';
|
|
|
+
|
|
|
+// 设置集成测试钩子
|
|
|
+setupIntegrationDatabaseHooksWithEntities([UserEntity, Role, TenantEntityMt, File])
|
|
|
+
|
|
|
+describe('租户管理API集成测试', () => {
|
|
|
+ let client: ReturnType<typeof testClient<typeof tenantRoutes>>;
|
|
|
+ let superAdminToken: string;
|
|
|
+ let regularUserToken: string;
|
|
|
+ let testUser: UserEntity;
|
|
|
+ let superAdminUser: UserEntity;
|
|
|
+
|
|
|
+ beforeEach(async () => {
|
|
|
+ // 创建测试客户端
|
|
|
+ client = testClient(tenantRoutes);
|
|
|
+
|
|
|
+ // 获取数据源
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
+
|
|
|
+ // 创建测试用户
|
|
|
+ const userRepository = dataSource.getRepository(UserEntity);
|
|
|
+ const roleRepository = dataSource.getRepository(Role);
|
|
|
+
|
|
|
+ // 创建超级管理员用户(ID为1)
|
|
|
+ superAdminUser = userRepository.create({
|
|
|
+ id: 1,
|
|
|
+ username: 'superadmin',
|
|
|
+ password: 'hashed_password',
|
|
|
+ nickname: '超级管理员',
|
|
|
+ status: 1
|
|
|
+ });
|
|
|
+ await userRepository.save(superAdminUser);
|
|
|
+
|
|
|
+ // 创建普通测试用户
|
|
|
+ testUser = userRepository.create({
|
|
|
+ username: 'testuser',
|
|
|
+ password: 'hashed_password',
|
|
|
+ nickname: '测试用户',
|
|
|
+ status: 1
|
|
|
+ });
|
|
|
+ await userRepository.save(testUser);
|
|
|
+
|
|
|
+ // 生成token
|
|
|
+ superAdminToken = JWTUtil.generateToken(superAdminUser);
|
|
|
+ regularUserToken = JWTUtil.generateToken(testUser);
|
|
|
+ });
|
|
|
+
|
|
|
+ afterEach(async () => {
|
|
|
+ vi.clearAllMocks();
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('创建租户', () => {
|
|
|
+ it('超级管理员应该能够创建租户', async () => {
|
|
|
+ const response = await client.index.$post({
|
|
|
+ json: {
|
|
|
+ name: '测试租户',
|
|
|
+ code: 'test-tenant',
|
|
|
+ contactName: '联系人',
|
|
|
+ phone: '13800138000',
|
|
|
+ email: 'test@example.com',
|
|
|
+ status: 1
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${superAdminToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(201);
|
|
|
+ const data = await response.json();
|
|
|
+ expect(data.name).toBe('测试租户');
|
|
|
+ expect(data.code).toBe('test-tenant');
|
|
|
+ expect(data.status).toBe(1);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('普通用户不应该能够创建租户', async () => {
|
|
|
+ const response = await client.index.$post({
|
|
|
+ json: {
|
|
|
+ name: '测试租户',
|
|
|
+ code: 'test-tenant',
|
|
|
+ contactName: '联系人',
|
|
|
+ phone: '13800138000',
|
|
|
+ email: 'test@example.com',
|
|
|
+ status: 1
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${regularUserToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(403);
|
|
|
+ const data = await response.json();
|
|
|
+ expect(data.message).toContain('Access denied');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('未认证用户不应该能够创建租户', async () => {
|
|
|
+ const response = await client.index.$post({
|
|
|
+ json: {
|
|
|
+ name: '测试租户',
|
|
|
+ code: 'test-tenant',
|
|
|
+ contactName: '联系人',
|
|
|
+ phone: '13800138000',
|
|
|
+ email: 'test@example.com',
|
|
|
+ status: 1
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(401);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('获取租户列表', () => {
|
|
|
+ beforeEach(async () => {
|
|
|
+ // 创建测试租户数据
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
+ const tenantRepository = dataSource.getRepository(TenantEntityMt);
|
|
|
+
|
|
|
+ await tenantRepository.save([
|
|
|
+ {
|
|
|
+ name: '租户A',
|
|
|
+ code: 'tenant-a',
|
|
|
+ contactName: '联系人A',
|
|
|
+ phone: '13800138001',
|
|
|
+ email: 'a@example.com',
|
|
|
+ status: 1,
|
|
|
+ createdBy: 1
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: '租户B',
|
|
|
+ code: 'tenant-b',
|
|
|
+ contactName: '联系人B',
|
|
|
+ phone: '13800138002',
|
|
|
+ email: 'b@example.com',
|
|
|
+ status: 2,
|
|
|
+ createdBy: 1
|
|
|
+ }
|
|
|
+ ]);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('超级管理员应该能够获取租户列表', async () => {
|
|
|
+ const response = await client.index.$get({
|
|
|
+ query: {}
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${superAdminToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ console.debug('列表查询响应状态:', response.status);
|
|
|
+ if (response.status !== 200) {
|
|
|
+ const errorData = await response.json();
|
|
|
+ console.debug('错误响应:', errorData);
|
|
|
+ }
|
|
|
+
|
|
|
+ expect(response.status).toBe(200);
|
|
|
+ const data = await response.json();
|
|
|
+ expect(data.data).toHaveLength(2);
|
|
|
+ expect(data.pagination.total).toBe(2);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('普通用户不应该能够获取租户列表', async () => {
|
|
|
+ const response = await client.index.$get({
|
|
|
+ query: {}
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${regularUserToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(403);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('获取单个租户', () => {
|
|
|
+ let testTenant: TenantEntityMt;
|
|
|
+
|
|
|
+ beforeEach(async () => {
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
+ const tenantRepository = dataSource.getRepository(TenantEntityMt);
|
|
|
+
|
|
|
+ testTenant = await tenantRepository.save({
|
|
|
+ name: '测试租户',
|
|
|
+ code: 'test-tenant',
|
|
|
+ contactName: '联系人',
|
|
|
+ phone: '13800138000',
|
|
|
+ email: 'test@example.com',
|
|
|
+ status: 1,
|
|
|
+ createdBy: 1
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('超级管理员应该能够获取租户详情', async () => {
|
|
|
+ const response = await client[':id'].$get({
|
|
|
+ param: { id: testTenant.id.toString() }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${superAdminToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(200);
|
|
|
+ const data = await response.json();
|
|
|
+ expect(data.name).toBe('测试租户');
|
|
|
+ expect(data.code).toBe('test-tenant');
|
|
|
+ });
|
|
|
+
|
|
|
+ it('普通用户不应该能够获取租户详情', async () => {
|
|
|
+ const response = await client[':id'].$get({
|
|
|
+ param: { id: testTenant.id.toString() }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${regularUserToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(403);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('更新租户', () => {
|
|
|
+ let testTenant: TenantEntityMt;
|
|
|
+
|
|
|
+ beforeEach(async () => {
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
+ const tenantRepository = dataSource.getRepository(TenantEntityMt);
|
|
|
+
|
|
|
+ testTenant = await tenantRepository.save({
|
|
|
+ name: '测试租户',
|
|
|
+ code: 'test-tenant',
|
|
|
+ contactName: '联系人',
|
|
|
+ phone: '13800138000',
|
|
|
+ email: 'test@example.com',
|
|
|
+ status: 1,
|
|
|
+ createdBy: 1
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('超级管理员应该能够更新租户', async () => {
|
|
|
+ const response = await client[':id'].$put({
|
|
|
+ param: { id: testTenant.id.toString() },
|
|
|
+ json: {
|
|
|
+ name: '更新后的租户',
|
|
|
+ contactName: '新联系人',
|
|
|
+ phone: '13900139000',
|
|
|
+ status: 2
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${superAdminToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(200);
|
|
|
+ const data = await response.json();
|
|
|
+ expect(data.name).toBe('更新后的租户');
|
|
|
+ expect(data.contactName).toBe('新联系人');
|
|
|
+ expect(data.status).toBe(2);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('普通用户不应该能够更新租户', async () => {
|
|
|
+ const response = await client[':id'].$put({
|
|
|
+ param: { id: testTenant.id.toString() },
|
|
|
+ json: {
|
|
|
+ name: '更新后的租户'
|
|
|
+ }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${regularUserToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(403);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('删除租户', () => {
|
|
|
+ let testTenant: TenantEntityMt;
|
|
|
+
|
|
|
+ beforeEach(async () => {
|
|
|
+ const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
+ const tenantRepository = dataSource.getRepository(TenantEntityMt);
|
|
|
+
|
|
|
+ testTenant = await tenantRepository.save({
|
|
|
+ name: '测试租户',
|
|
|
+ code: 'test-tenant',
|
|
|
+ contactName: '联系人',
|
|
|
+ phone: '13800138000',
|
|
|
+ email: 'test@example.com',
|
|
|
+ status: 1,
|
|
|
+ createdBy: 1
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ it('超级管理员应该能够删除租户', async () => {
|
|
|
+ const response = await client[':id'].$delete({
|
|
|
+ param: { id: testTenant.id.toString() }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${superAdminToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(204);
|
|
|
+ });
|
|
|
+
|
|
|
+ it('普通用户不应该能够删除租户', async () => {
|
|
|
+ const response = await client[':id'].$delete({
|
|
|
+ param: { id: testTenant.id.toString() }
|
|
|
+ }, {
|
|
|
+ headers: {
|
|
|
+ Authorization: `Bearer ${regularUserToken}`
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ expect(response.status).toBe(403);
|
|
|
+ });
|
|
|
+ });
|
|
|
+});
|