docs/ai-reading-improvements-20260119 #52

Merged
moyin merged 5 commits from docs/ai-reading-improvements-20260119 into main 2026-01-19 18:38:01 +08:00
2 changed files with 36 additions and 25 deletions
Showing only changes of commit 1849415b11 - Show all commits

View File

@@ -7,9 +7,12 @@
* - 接口导出验证 * - 接口导出验证
* *
* @author moyin * @author moyin
* @version 1.0.0 * @version 1.0.1
* @since 2026-01-14 * @since 2026-01-14
* @lastModified 2026-01-14 * @lastModified 2026-01-19
*
* 修改记录:
* - 2026-01-19 moyin: Bug修复 - 添加缺失的ZulipAccountsService Mock配置
*/ */
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
@@ -33,6 +36,7 @@ describe('ChatModule', () => {
createUserClient: jest.fn(), createUserClient: jest.fn(),
destroyUserClient: jest.fn(), destroyUserClient: jest.fn(),
sendMessage: jest.fn(), sendMessage: jest.fn(),
getUserClient: jest.fn(),
}; };
const mockZulipConfigService = { const mockZulipConfigService = {
@@ -61,6 +65,10 @@ describe('ChatModule', () => {
verifyToken: jest.fn(), verifyToken: jest.fn(),
}; };
const mockZulipAccountsService = {
findByGameUserId: jest.fn(),
};
beforeEach(async () => { beforeEach(async () => {
// 禁用日志输出 // 禁用日志输出
jest.spyOn(Logger.prototype, 'log').mockImplementation(); jest.spyOn(Logger.prototype, 'log').mockImplementation();
@@ -97,6 +105,10 @@ describe('ChatModule', () => {
provide: LoginCoreService, provide: LoginCoreService,
useValue: mockLoginCoreService, useValue: mockLoginCoreService,
}, },
{
provide: 'ZulipAccountsService',
useValue: mockZulipAccountsService,
},
], ],
}).compile(); }).compile();

View File

@@ -8,9 +8,12 @@
* - Token验证和错误处理 * - Token验证和错误处理
* *
* @author moyin * @author moyin
* @version 1.0.0 * @version 1.0.1
* @since 2026-01-14 * @since 2026-01-14
* @lastModified 2026-01-14 * @lastModified 2026-01-19
*
* 修改记录:
* - 2026-01-19 moyin: 修复handlePlayerLogout测试删除不再调用的deleteApiKey断言和过时测试用例
*/ */
import { Test, TestingModule } from '@nestjs/testing'; import { Test, TestingModule } from '@nestjs/testing';
@@ -51,6 +54,7 @@ describe('ChatService', () => {
createUserClient: jest.fn(), createUserClient: jest.fn(),
destroyUserClient: jest.fn(), destroyUserClient: jest.fn(),
sendMessage: jest.fn(), sendMessage: jest.fn(),
getUserClient: jest.fn(),
}; };
const mockApiKeySecurityService = { const mockApiKeySecurityService = {
@@ -62,6 +66,10 @@ describe('ChatService', () => {
verifyToken: jest.fn(), verifyToken: jest.fn(),
}; };
const mockZulipAccountsService = {
findByGameUserId: jest.fn(),
};
mockWebSocketGateway = { mockWebSocketGateway = {
broadcastToMap: jest.fn(), broadcastToMap: jest.fn(),
sendToPlayer: jest.fn(), sendToPlayer: jest.fn(),
@@ -90,6 +98,10 @@ describe('ChatService', () => {
provide: LoginCoreService, provide: LoginCoreService,
useValue: mockLoginCoreService, useValue: mockLoginCoreService,
}, },
{
provide: 'ZulipAccountsService',
useValue: mockZulipAccountsService,
},
], ],
}).compile(); }).compile();
@@ -100,6 +112,14 @@ describe('ChatService', () => {
apiKeySecurityService = module.get('API_KEY_SECURITY_SERVICE'); apiKeySecurityService = module.get('API_KEY_SECURITY_SERVICE');
loginCoreService = module.get(LoginCoreService); loginCoreService = module.get(LoginCoreService);
// 设置默认的mock行为
// ZulipAccountsService默认返回null用户没有Zulip账号
const zulipAccountsService = module.get('ZulipAccountsService');
zulipAccountsService.findByGameUserId.mockResolvedValue(null);
// ZulipClientPool的getUserClient默认返回null
zulipClientPool.getUserClient.mockResolvedValue(null);
// 设置WebSocket网关 // 设置WebSocket网关
service.setWebSocketGateway(mockWebSocketGateway); service.setWebSocketGateway(mockWebSocketGateway);
@@ -220,14 +240,12 @@ describe('ChatService', () => {
createdAt: new Date(), createdAt: new Date(),
}); });
zulipClientPool.destroyUserClient.mockResolvedValue(undefined); zulipClientPool.destroyUserClient.mockResolvedValue(undefined);
apiKeySecurityService.deleteApiKey.mockResolvedValue(undefined);
sessionService.destroySession.mockResolvedValue(true); sessionService.destroySession.mockResolvedValue(true);
await service.handlePlayerLogout(socketId, 'manual'); await service.handlePlayerLogout(socketId, 'manual');
expect(sessionService.getSession).toHaveBeenCalledWith(socketId); expect(sessionService.getSession).toHaveBeenCalledWith(socketId);
expect(zulipClientPool.destroyUserClient).toHaveBeenCalledWith(userId); expect(zulipClientPool.destroyUserClient).toHaveBeenCalledWith(userId);
expect(apiKeySecurityService.deleteApiKey).toHaveBeenCalledWith(userId);
expect(sessionService.destroySession).toHaveBeenCalledWith(socketId); expect(sessionService.destroySession).toHaveBeenCalledWith(socketId);
}); });
@@ -257,25 +275,6 @@ describe('ChatService', () => {
expect(sessionService.destroySession).toHaveBeenCalled(); expect(sessionService.destroySession).toHaveBeenCalled();
}); });
it('应该处理API Key清理失败', async () => {
sessionService.getSession.mockResolvedValue({
socketId,
userId,
username: 'testuser',
zulipQueueId: 'queue_123',
currentMap: 'whale_port',
position: { x: 400, y: 300 },
lastActivity: new Date(),
createdAt: new Date(),
});
apiKeySecurityService.deleteApiKey.mockRejectedValue(new Error('Redis error'));
sessionService.destroySession.mockResolvedValue(true);
await service.handlePlayerLogout(socketId);
expect(sessionService.destroySession).toHaveBeenCalled();
});
}); });
describe('sendChatMessage', () => { describe('sendChatMessage', () => {