Просмотр исходного кода

✅ test(supplier): 添加供应商管理集成测试

- 新增管理员供应商管理API集成测试,覆盖CRUD操作和权限验证
- 新增用户供应商管理API集成测试,验证数据权限控制
- 测试管理员权限:创建、查询、更新、删除其他用户供应商
- 测试用户权限:仅能操作自己的供应商数据
- 验证供应商状态管理和登录统计功能
- 更新Claude配置允许cat命令执行
yourname 1 месяц назад
Родитель
Сommit
a6022ff8a4

+ 2 - 1
.claude/settings.local.json

@@ -43,7 +43,8 @@
       "Bash(pnpm db:restore)",
       "Bash(pnpm test:coverage:*)",
       "Bash(pnpm run test:integration:*)",
-      "Bash(pnpm install:*)"
+      "Bash(pnpm install:*)",
+      "Bash(cat:*)"
     ],
     "deny": [],
     "ask": []

+ 584 - 0
packages/supplier-module/tests/integration/admin-routes.integration.test.ts

@@ -0,0 +1,584 @@
+import { describe, it, expect, beforeEach } 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 { adminSupplierRoutes } from '../../src/routes';
+import { Supplier } from '../../src/entities';
+
+// 设置集成测试钩子
+setupIntegrationDatabaseHooksWithEntities([UserEntity, Role, Supplier])
+
+describe('管理员供应商管理API集成测试', () => {
+  let client: ReturnType<typeof testClient<typeof adminSupplierRoutes>>;
+  let adminToken: string;
+  let testUser: UserEntity;
+  let testAdmin: UserEntity;
+
+  beforeEach(async () => {
+    // 创建测试客户端
+    client = testClient(adminSupplierRoutes);
+
+    // 获取数据源
+    const dataSource = await IntegrationTestDatabase.getDataSource();
+
+    // 创建测试用户
+    const userRepository = dataSource.getRepository(UserEntity);
+    testUser = userRepository.create({
+      username: `test_user_${Date.now()}`,
+      password: 'test_password',
+      nickname: '测试用户',
+      registrationSource: 'web'
+    });
+    await userRepository.save(testUser);
+
+    // 创建测试管理员用户
+    testAdmin = userRepository.create({
+      username: `test_admin_${Date.now()}`,
+      password: 'admin_password',
+      nickname: '测试管理员',
+      registrationSource: 'web'
+    });
+    await userRepository.save(testAdmin);
+
+    // 生成测试管理员的token
+    adminToken = JWTUtil.generateToken({
+      id: testAdmin.id,
+      username: testAdmin.username,
+      roles: [{name:'admin'}]
+    });
+  });
+
+  describe('GET /suppliers', () => {
+    it('应该返回供应商列表', async () => {
+      const response = await client.index.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      console.debug('供应商列表响应状态:', response.status);
+      expect(response.status).toBe(200);
+
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data).toHaveProperty('data');
+        expect(Array.isArray(data.data)).toBe(true);
+      }
+    });
+
+    it('应该拒绝未认证用户的访问', async () => {
+      const response = await client.index.$get({
+        query: {}
+      });
+      expect(response.status).toBe(401);
+    });
+  });
+
+  describe('POST /suppliers', () => {
+    it('应该成功创建供应商', async () => {
+      const createData = {
+        name: '管理员创建供应商',
+        username: `admin_created_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138000',
+        realname: '管理员创建供应商',
+        state: 1
+      };
+
+      const response = await client.index.$post({
+        json: createData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      console.debug('创建供应商响应状态:', response.status);
+      if (response.status !== 201) {
+        const errorData = await response.json();
+        console.debug('创建供应商错误响应:', errorData);
+      }
+      expect(response.status).toBe(201);
+
+      if (response.status === 201) {
+        const data = await response.json();
+        expect(data).toHaveProperty('id');
+        expect(data.name).toBe(createData.name);
+        expect(data.username).toBe(createData.username);
+        expect(data.phone).toBe(createData.phone);
+        expect(data.realname).toBe(createData.realname);
+        expect(data.state).toBe(createData.state);
+      }
+    });
+
+    it('应该验证创建供应商的必填字段', async () => {
+      const invalidData = {
+        // 缺少必填字段
+        name: '',
+        username: '',
+        password: '',
+        phone: '',
+        realname: ''
+      };
+
+      const response = await client.index.$post({
+        json: invalidData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(response.status).toBe(400);
+    });
+  });
+
+  describe('GET /suppliers/:id', () => {
+    it('应该返回指定供应商的详情', async () => {
+      // 先创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const testSupplier = supplierRepository.create({
+        name: '测试供应商详情',
+        username: `test_supplier_detail_${Date.now()}`,
+        password: 'password123',
+        phone: '13600136000',
+        realname: '测试供应商详情',
+        loginNum: 5,
+        loginTime: Date.now(),
+        loginIp: '192.168.1.1',
+        lastLoginTime: Date.now(),
+        lastLoginIp: '192.168.1.1',
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(testSupplier);
+
+      const response = await client[':id'].$get({
+        param: { id: testSupplier.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      console.debug('供应商详情响应状态:', response.status);
+      expect(response.status).toBe(200);
+
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data.id).toBe(testSupplier.id);
+        expect(data.name).toBe(testSupplier.name);
+        expect(data.username).toBe(testSupplier.username);
+        expect(data.phone).toBe(testSupplier.phone);
+        expect(data.realname).toBe(testSupplier.realname);
+      }
+    });
+
+    it('应该处理不存在的供应商', async () => {
+      const response = await client[':id'].$get({
+        param: { id: 999999 }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(response.status).toBe(404);
+    });
+  });
+
+  describe('PUT /suppliers/:id', () => {
+    it('应该成功更新供应商', async () => {
+      // 先创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const testSupplier = supplierRepository.create({
+        name: '原始供应商',
+        username: `original_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13500135000',
+        realname: '原始供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(testSupplier);
+
+      const updateData = {
+        name: '更新后的供应商',
+        phone: '13700137000',
+        realname: '更新后的供应商',
+        state: 2
+      };
+
+      const response = await client[':id'].$put({
+        param: { id: testSupplier.id },
+        json: updateData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      console.debug('更新供应商响应状态:', response.status);
+      expect(response.status).toBe(200);
+
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data.name).toBe(updateData.name);
+        expect(data.phone).toBe(updateData.phone);
+        expect(data.realname).toBe(updateData.realname);
+        expect(data.state).toBe(updateData.state);
+      }
+    });
+  });
+
+  describe('DELETE /suppliers/:id', () => {
+    it('应该成功删除供应商', async () => {
+      // 先创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const testSupplier = supplierRepository.create({
+        name: '待删除供应商',
+        username: `delete_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13400134000',
+        realname: '待删除供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(testSupplier);
+
+      const response = await client[':id'].$delete({
+        param: { id: testSupplier.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      console.debug('删除供应商响应状态:', response.status);
+      expect(response.status).toBe(204);
+
+      // 验证供应商确实被删除
+      const deletedSupplier = await supplierRepository.findOne({
+        where: { id: testSupplier.id }
+      });
+      expect(deletedSupplier).toBeNull();
+    });
+  });
+
+  describe('管理员权限测试', () => {
+    it('管理员应该可以为其他用户创建供应商', async () => {
+      const createData = {
+        name: '为其他用户创建供应商',
+        username: `other_user_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138001',
+        realname: '为其他用户创建供应商',
+        state: 1,
+        createdBy: testUser.id // 管理员可以指定创建者
+      };
+
+      const response = await client.index.$post({
+        json: createData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      console.debug('管理员为其他用户创建供应商响应状态:', response.status);
+      expect(response.status).toBe(201);
+
+      if (response.status === 201) {
+        const data = await response.json();
+        expect(data.createdBy).toBe(testUser.id); // 验证供应商确实属于其他用户
+        expect(data.name).toBe(createData.name);
+      }
+    });
+
+    it('管理员应该可以访问所有用户的供应商', async () => {
+      // 为测试用户创建一些供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+
+      const userSupplier1 = supplierRepository.create({
+        name: '用户供应商1',
+        username: `user_supplier1_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138002',
+        realname: '用户供应商1',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(userSupplier1);
+
+      const userSupplier2 = supplierRepository.create({
+        name: '用户供应商2',
+        username: `user_supplier2_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138003',
+        realname: '用户供应商2',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(userSupplier2);
+
+      // 管理员应该能看到所有供应商
+      const response = await client.index.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      const data = await response.json();
+      if (data && 'data' in data) {
+        expect(Array.isArray(data.data)).toBe(true);
+        expect(data.data.length).toBeGreaterThanOrEqual(2); // 至少包含我们创建的两个供应商
+      }
+    });
+
+    it('管理员应该可以更新其他用户的供应商', async () => {
+      // 先为测试用户创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const testSupplier = supplierRepository.create({
+        name: '原始供应商',
+        username: `original_supplier_admin_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138004',
+        realname: '原始供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(testSupplier);
+
+      const updateData = {
+        name: '管理员更新的供应商',
+        phone: '13900139000',
+        realname: '管理员更新的供应商'
+      };
+
+      const response = await client[':id'].$put({
+        param: { id: testSupplier.id },
+        json: updateData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      console.debug('管理员更新其他用户供应商响应状态:', response.status);
+      expect(response.status).toBe(200);
+
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data.name).toBe(updateData.name);
+        expect(data.phone).toBe(updateData.phone);
+        expect(data.realname).toBe(updateData.realname);
+      }
+    });
+
+    it('管理员应该可以删除其他用户的供应商', async () => {
+      // 先为测试用户创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const testSupplier = supplierRepository.create({
+        name: '待删除供应商',
+        username: `delete_supplier_admin_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138005',
+        realname: '待删除供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(testSupplier);
+
+      const response = await client[':id'].$delete({
+        param: { id: testSupplier.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      console.debug('管理员删除其他用户供应商响应状态:', response.status);
+      expect(response.status).toBe(204);
+
+      // 验证供应商确实被删除
+      const deletedSupplier = await supplierRepository.findOne({
+        where: { id: testSupplier.id }
+      });
+      expect(deletedSupplier).toBeNull();
+    });
+
+    it('管理员应该可以查询指定用户的供应商', async () => {
+      // 为测试用户创建一些供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+
+      const userSupplier = supplierRepository.create({
+        name: '指定用户供应商',
+        username: `specified_user_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138006',
+        realname: '指定用户供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(userSupplier);
+
+      // 管理员可以查询指定用户的供应商
+      const response = await client.index.$get({
+        query: { filters: JSON.stringify({ createdBy: testUser.id }) }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(response.status).toBe(200);
+      const data = await response.json();
+      if (data && 'data' in data) {
+        expect(Array.isArray(data.data)).toBe(true);
+
+        // 验证返回的供应商都属于指定用户
+        if (data.data.length > 0) {
+          data.data.forEach((supplier: any) => {
+            expect(supplier.createdBy).toBe(testUser.id);
+          });
+        }
+      }
+    });
+  });
+
+  describe('供应商状态管理', () => {
+    it('应该支持供应商状态管理', async () => {
+      // 创建启用状态的供应商
+      const createData = {
+        name: '状态测试供应商',
+        username: `status_test_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138007',
+        realname: '状态测试供应商',
+        state: 1 // 启用状态
+      };
+
+      const createResponse = await client.index.$post({
+        json: createData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(createResponse.status).toBe(201);
+      const createdData = await createResponse.json();
+
+      // 更新为禁用状态
+      const updateResponse = await client[':id'].$put({
+        param: { id: createdData.id },
+        json: { state: 2 } // 禁用状态
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(updateResponse.status).toBe(200);
+      const updatedData = await updateResponse.json();
+      expect(updatedData.state).toBe(2);
+    });
+  });
+
+  describe('供应商登录统计', () => {
+    it('应该支持供应商登录统计功能', async () => {
+      // 创建供应商
+      const createData = {
+        name: '登录统计供应商',
+        username: `login_stat_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138008',
+        realname: '登录统计供应商',
+        state: 1
+      };
+
+      const createResponse = await client.index.$post({
+        json: createData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(createResponse.status).toBe(201);
+      const createdData = await createResponse.json();
+
+      // 验证初始登录统计
+      expect(createdData.loginNum).toBe(0);
+      expect(createdData.loginTime).toBe(0);
+      expect(createdData.lastLoginTime).toBe(0);
+      expect(createdData.loginIp).toBeNull();
+      expect(createdData.lastLoginIp).toBeNull();
+
+      // 获取供应商详情验证字段存在
+      const getResponse = await client[':id'].$get({
+        param: { id: createdData.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${adminToken}`
+        }
+      });
+
+      expect(getResponse.status).toBe(200);
+      const supplierData = await getResponse.json();
+      expect(supplierData).toHaveProperty('loginNum');
+      expect(supplierData).toHaveProperty('loginTime');
+      expect(supplierData).toHaveProperty('lastLoginTime');
+      expect(supplierData).toHaveProperty('loginIp');
+      expect(supplierData).toHaveProperty('lastLoginIp');
+    });
+  });
+});

+ 631 - 0
packages/supplier-module/tests/integration/user-routes.integration.test.ts

@@ -0,0 +1,631 @@
+import { describe, it, expect, beforeEach } 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 { userSupplierRoutes } from '../../src/routes';
+import { Supplier } from '../../src/entities';
+
+// 设置集成测试钩子
+setupIntegrationDatabaseHooksWithEntities([UserEntity, Role, Supplier])
+
+describe('用户供应商管理API集成测试', () => {
+  let client: ReturnType<typeof testClient<typeof userSupplierRoutes>>;
+  let userToken: string;
+  let otherUserToken: string;
+  let testUser: UserEntity;
+  let otherUser: UserEntity;
+
+  beforeEach(async () => {
+    // 创建测试客户端
+    client = testClient(userSupplierRoutes);
+
+    // 获取数据源
+    const dataSource = await IntegrationTestDatabase.getDataSource();
+
+    // 创建测试用户
+    const userRepository = dataSource.getRepository(UserEntity);
+    testUser = userRepository.create({
+      username: `test_user_${Date.now()}`,
+      password: 'test_password',
+      nickname: '测试用户',
+      registrationSource: 'web'
+    });
+    await userRepository.save(testUser);
+
+    // 创建其他用户
+    otherUser = userRepository.create({
+      username: `other_user_${Date.now()}`,
+      password: 'other_password',
+      nickname: '其他用户',
+      registrationSource: 'web'
+    });
+    await userRepository.save(otherUser);
+
+    // 生成测试用户的token
+    userToken = JWTUtil.generateToken({
+      id: testUser.id,
+      username: testUser.username,
+      roles: [{name:'user'}]
+    });
+
+    // 生成其他用户的token
+    otherUserToken = JWTUtil.generateToken({
+      id: otherUser.id,
+      username: otherUser.username,
+      roles: [{name:'user'}]
+    });
+  });
+
+  describe('GET /suppliers', () => {
+    it('应该返回当前用户的供应商列表', async () => {
+      // 为测试用户创建一些供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+
+      const userSupplier1 = supplierRepository.create({
+        name: '用户供应商1',
+        username: `user_supplier1_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138001',
+        realname: '用户供应商1',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(userSupplier1);
+
+      const userSupplier2 = supplierRepository.create({
+        name: '用户供应商2',
+        username: `user_supplier2_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138002',
+        realname: '用户供应商2',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(userSupplier2);
+
+      // 为其他用户创建一个供应商,确保不会返回
+      const otherUserSupplier = supplierRepository.create({
+        name: '其他用户供应商',
+        username: `other_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138003',
+        realname: '其他用户供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: otherUser.id
+      });
+      await supplierRepository.save(otherUserSupplier);
+
+      const response = await client.index.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      console.debug('用户供应商列表响应状态:', response.status);
+      expect(response.status).toBe(200);
+
+      if (response.status === 200) {
+        const data = await response.json();
+        if (data && 'data' in data) {
+          expect(Array.isArray(data.data)).toBe(true);
+          // 应该只返回当前用户的供应商
+          data.data.forEach((supplier: any) => {
+            expect(supplier.createdBy).toBe(testUser.id);
+          });
+        }
+      }
+    });
+
+    it('应该拒绝未认证用户的访问', async () => {
+      const response = await client.index.$get({
+        query: {}
+      });
+      expect(response.status).toBe(401);
+    });
+  });
+
+  describe('POST /suppliers', () => {
+    it('应该成功创建供应商并自动使用当前用户ID', async () => {
+      const createData = {
+        name: '测试供应商',
+        username: `test_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138000',
+        realname: '测试供应商',
+        state: 1
+      };
+
+      const response = await client.index.$post({
+        json: createData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      console.debug('用户创建供应商响应状态:', response.status);
+      expect(response.status).toBe(201);
+
+      if (response.status === 201) {
+        const data = await response.json();
+        console.debug('用户创建供应商响应数据:', JSON.stringify(data, null, 2));
+        expect(data).toHaveProperty('id');
+        expect(data.createdBy).toBe(testUser.id); // 自动使用当前用户ID
+        expect(data.name).toBe(createData.name);
+        expect(data.username).toBe(createData.username);
+        expect(data.phone).toBe(createData.phone);
+        expect(data.realname).toBe(createData.realname);
+      }
+    });
+
+    it('应该验证创建供应商的必填字段', async () => {
+      const invalidData = {
+        // 缺少必填字段
+        name: '',
+        username: '',
+        password: '',
+        phone: '',
+        realname: ''
+      };
+
+      const response = await client.index.$post({
+        json: invalidData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(400);
+    });
+  });
+
+  describe('GET /suppliers/:id', () => {
+    it('应该返回当前用户的供应商详情', async () => {
+      // 先为当前用户创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const testSupplier = supplierRepository.create({
+        name: '测试供应商详情',
+        username: `test_supplier_detail_${Date.now()}`,
+        password: 'password123',
+        phone: '13600136000',
+        realname: '测试供应商详情',
+        loginNum: 5,
+        loginTime: Date.now(),
+        loginIp: '192.168.1.1',
+        lastLoginTime: Date.now(),
+        lastLoginIp: '192.168.1.1',
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(testSupplier);
+
+      const response = await client[':id'].$get({
+        param: { id: testSupplier.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      console.debug('用户供应商详情响应状态:', response.status);
+      expect(response.status).toBe(200);
+
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data.id).toBe(testSupplier.id);
+        expect(data.createdBy).toBe(testUser.id);
+        expect(data.name).toBe(testSupplier.name);
+        expect(data.username).toBe(testSupplier.username);
+        expect(data.phone).toBe(testSupplier.phone);
+        expect(data.realname).toBe(testSupplier.realname);
+      }
+    });
+
+    it('应该拒绝访问其他用户的供应商', async () => {
+      // 为其他用户创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const otherUserSupplier = supplierRepository.create({
+        name: '其他用户供应商',
+        username: `other_supplier_detail_${Date.now()}`,
+        password: 'password123',
+        phone: '13600136001',
+        realname: '其他用户供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: otherUser.id
+      });
+      await supplierRepository.save(otherUserSupplier);
+
+      // 当前用户尝试访问其他用户的供应商
+      const response = await client[':id'].$get({
+        param: { id: otherUserSupplier.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      console.debug('用户访问其他用户供应商响应状态:', response.status);
+      expect(response.status).toBe(404); // 应该返回404,而不是403
+    });
+
+    it('应该处理不存在的供应商', async () => {
+      const response = await client[':id'].$get({
+        param: { id: 999999 }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(response.status).toBe(404);
+    });
+  });
+
+  describe('PUT /suppliers/:id', () => {
+    it('应该成功更新当前用户的供应商', async () => {
+      // 先为当前用户创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const testSupplier = supplierRepository.create({
+        name: '原始供应商',
+        username: `original_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13500135000',
+        realname: '原始供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(testSupplier);
+
+      const updateData = {
+        name: '更新后的供应商',
+        phone: '13700137000',
+        realname: '更新后的供应商',
+        state: 2
+      };
+
+      const response = await client[':id'].$put({
+        param: { id: testSupplier.id },
+        json: updateData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      console.debug('用户更新供应商响应状态:', response.status);
+      expect(response.status).toBe(200);
+
+      if (response.status === 200) {
+        const data = await response.json();
+        expect(data.name).toBe(updateData.name);
+        expect(data.phone).toBe(updateData.phone);
+        expect(data.realname).toBe(updateData.realname);
+        expect(data.state).toBe(updateData.state);
+      }
+    });
+
+    it('应该拒绝更新其他用户的供应商', async () => {
+      // 为其他用户创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const otherUserSupplier = supplierRepository.create({
+        name: '其他用户供应商',
+        username: `other_supplier_update_${Date.now()}`,
+        password: 'password123',
+        phone: '13500135001',
+        realname: '其他用户供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: otherUser.id
+      });
+      await supplierRepository.save(otherUserSupplier);
+
+      const updateData = {
+        name: '尝试更新的供应商',
+        phone: '13700137001',
+        realname: '尝试更新的供应商'
+      };
+
+      // 当前用户尝试更新其他用户的供应商
+      const response = await client[':id'].$put({
+        param: { id: otherUserSupplier.id },
+        json: updateData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      console.debug('用户更新其他用户供应商响应状态:', response.status);
+      expect(response.status).toBe(403); // 数据权限控制返回403
+    });
+  });
+
+  describe('DELETE /suppliers/:id', () => {
+    it('应该成功删除当前用户的供应商', async () => {
+      // 先为当前用户创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const testSupplier = supplierRepository.create({
+        name: '待删除供应商',
+        username: `delete_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13400134000',
+        realname: '待删除供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(testSupplier);
+
+      const response = await client[':id'].$delete({
+        param: { id: testSupplier.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      console.debug('用户删除供应商响应状态:', response.status);
+      expect(response.status).toBe(204);
+
+      // 验证供应商确实被删除
+      const deletedSupplier = await supplierRepository.findOne({
+        where: { id: testSupplier.id }
+      });
+      expect(deletedSupplier).toBeNull();
+    });
+
+    it('应该拒绝删除其他用户的供应商', async () => {
+      // 为其他用户创建一个供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+      const otherUserSupplier = supplierRepository.create({
+        name: '其他用户供应商',
+        username: `other_supplier_delete_${Date.now()}`,
+        password: 'password123',
+        phone: '13400134001',
+        realname: '其他用户供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: otherUser.id
+      });
+      await supplierRepository.save(otherUserSupplier);
+
+      // 当前用户尝试删除其他用户的供应商
+      const response = await client[':id'].$delete({
+        param: { id: otherUserSupplier.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      console.debug('用户删除其他用户供应商响应状态:', response.status);
+      expect(response.status).toBe(403); // 数据权限控制返回403
+    });
+  });
+
+  describe('数据权限验证', () => {
+    it('用户应该只能访问和操作自己的数据', async () => {
+      // 为两个用户都创建供应商
+      const dataSource = await IntegrationTestDatabase.getDataSource();
+      const supplierRepository = dataSource.getRepository(Supplier);
+
+      const userSupplier = supplierRepository.create({
+        name: '用户供应商',
+        username: `user_supplier_perm_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138004',
+        realname: '用户供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: testUser.id
+      });
+      await supplierRepository.save(userSupplier);
+
+      const otherUserSupplier = supplierRepository.create({
+        name: '其他用户供应商',
+        username: `other_supplier_perm_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138005',
+        realname: '其他用户供应商',
+        loginNum: 0,
+        loginTime: 0,
+        loginIp: null,
+        lastLoginTime: 0,
+        lastLoginIp: null,
+        state: 1,
+        createdBy: otherUser.id
+      });
+      await supplierRepository.save(otherUserSupplier);
+
+      // 当前用户应该只能看到自己的供应商
+      const listResponse = await client.index.$get({
+        query: {}
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(listResponse.status).toBe(200);
+      const listData = await listResponse.json();
+      if (listData && 'data' in listData) {
+        expect(Array.isArray(listData.data)).toBe(true);
+        // 应该只包含当前用户的供应商
+        listData.data.forEach((supplier: any) => {
+          expect(supplier.createdBy).toBe(testUser.id);
+        });
+      }
+
+      // 当前用户应该无法访问其他用户的供应商详情
+      const getResponse = await client[':id'].$get({
+        param: { id: otherUserSupplier.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+      expect(getResponse.status).toBe(404);
+
+      // 当前用户应该无法更新其他用户的供应商
+      const updateResponse = await client[':id'].$put({
+        param: { id: otherUserSupplier.id },
+        json: { name: '尝试更新' }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+      expect(updateResponse.status).toBe(403);
+
+      // 当前用户应该无法删除其他用户的供应商
+      const deleteResponse = await client[':id'].$delete({
+        param: { id: otherUserSupplier.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+      expect(deleteResponse.status).toBe(403);
+    });
+  });
+
+  describe('供应商状态管理', () => {
+    it('应该支持供应商状态管理', async () => {
+      // 创建启用状态的供应商
+      const createData = {
+        name: '状态测试供应商',
+        username: `status_test_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138006',
+        realname: '状态测试供应商',
+        state: 1 // 启用状态
+      };
+
+      const createResponse = await client.index.$post({
+        json: createData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(createResponse.status).toBe(201);
+      const createdData = await createResponse.json();
+
+      // 更新为禁用状态
+      const updateResponse = await client[':id'].$put({
+        param: { id: createdData.id },
+        json: { state: 2 } // 禁用状态
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(updateResponse.status).toBe(200);
+      const updatedData = await updateResponse.json();
+      expect(updatedData.state).toBe(2);
+    });
+  });
+
+  describe('供应商登录统计', () => {
+    it('应该支持供应商登录统计功能', async () => {
+      // 创建供应商
+      const createData = {
+        name: '登录统计供应商',
+        username: `login_stat_supplier_${Date.now()}`,
+        password: 'password123',
+        phone: '13800138007',
+        realname: '登录统计供应商',
+        state: 1
+      };
+
+      const createResponse = await client.index.$post({
+        json: createData
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(createResponse.status).toBe(201);
+      const createdData = await createResponse.json();
+
+      // 验证初始登录统计
+      expect(createdData.loginNum).toBe(0);
+      expect(createdData.loginTime).toBe(0);
+      expect(createdData.lastLoginTime).toBe(0);
+      expect(createdData.loginIp).toBeNull();
+      expect(createdData.lastLoginIp).toBeNull();
+
+      // 获取供应商详情验证字段存在
+      const getResponse = await client[':id'].$get({
+        param: { id: createdData.id }
+      }, {
+        headers: {
+          'Authorization': `Bearer ${userToken}`
+        }
+      });
+
+      expect(getResponse.status).toBe(200);
+      const supplierData = await getResponse.json();
+      expect(supplierData).toHaveProperty('loginNum');
+      expect(supplierData).toHaveProperty('loginTime');
+      expect(supplierData).toHaveProperty('lastLoginTime');
+      expect(supplierData).toHaveProperty('loginIp');
+      expect(supplierData).toHaveProperty('lastLoginIp');
+    });
+  });
+});