Files
whale-town-end/src/core/zulip/services/user_registration.service.spec.ts
moyin 470b0b8dbf feat: 添加JWT认证系统和Zulip用户管理服务
- 新增JWT认证守卫(JwtAuthGuard)和当前用户装饰器(CurrentUser)
- 添加JWT使用示例和完整的认证流程文档
- 实现Zulip用户管理服务,支持用户查询、验证和管理
- 实现Zulip用户注册服务,支持新用户创建和注册流程
- 添加完整的单元测试覆盖
- 新增真实环境测试脚本,验证Zulip API集成
- 更新.gitignore,排除.kiro目录

主要功能:
- JWT令牌验证和用户信息提取
- 用户存在性检查和信息获取
- Zulip API集成和错误处理
- 完整的测试覆盖和文档
2026-01-06 15:17:05 +08:00

188 lines
5.5 KiB
TypeScript

/**
* Zulip用户注册服务测试
*
* 功能描述:
* - 测试UserRegistrationService的核心功能
* - 测试用户注册流程和验证逻辑
* - 测试错误处理和边界情况
*
* @author angjustinl
* @version 1.0.0
* @since 2025-01-06
*/
import { Test, TestingModule } from '@nestjs/testing';
import { UserRegistrationService, UserRegistrationRequest } from './user_registration.service';
import { IZulipConfigService } from '../interfaces/zulip-core.interfaces';
describe('UserRegistrationService', () => {
let service: UserRegistrationService;
let mockConfigService: jest.Mocked<IZulipConfigService>;
beforeEach(async () => {
// 创建模拟的配置服务
mockConfigService = {
getZulipConfig: jest.fn().mockReturnValue({
zulipServerUrl: 'https://test.zulip.com',
zulipBotEmail: 'bot@test.com',
zulipBotApiKey: 'test-api-key',
}),
getMapIdByStream: jest.fn(),
getStreamByMap: jest.fn(),
getMapConfig: jest.fn(),
hasMap: jest.fn(),
getAllMapIds: jest.fn(),
getMapConfigByStream: jest.fn(),
getAllStreams: jest.fn(),
hasStream: jest.fn(),
findObjectByTopic: jest.fn(),
getObjectsInMap: jest.fn(),
getTopicByObject: jest.fn(),
findNearbyObject: jest.fn(),
reloadConfig: jest.fn(),
validateConfig: jest.fn(),
getAllMapConfigs: jest.fn(),
getConfigStats: jest.fn(),
getConfigFilePath: jest.fn(),
configFileExists: jest.fn(),
enableConfigWatcher: jest.fn(),
disableConfigWatcher: jest.fn(),
isConfigWatcherEnabled: jest.fn(),
getFullConfiguration: jest.fn(),
updateConfigValue: jest.fn(),
exportMapConfig: jest.fn(),
} as jest.Mocked<IZulipConfigService>;
const module: TestingModule = await Test.createTestingModule({
providers: [
UserRegistrationService,
{
provide: 'ZULIP_CONFIG_SERVICE',
useValue: mockConfigService,
},
],
}).compile();
service = module.get<UserRegistrationService>(UserRegistrationService);
});
it('应该正确初始化服务', () => {
expect(service).toBeDefined();
});
describe('registerUser - 用户注册', () => {
it('应该成功注册有效用户', async () => {
const request: UserRegistrationRequest = {
email: 'test@example.com',
fullName: 'Test User',
password: 'password123',
};
const result = await service.registerUser(request);
expect(result.success).toBe(true);
expect(result.email).toBe(request.email);
expect(result.userId).toBeDefined();
expect(result.apiKey).toBeDefined();
expect(result.error).toBeUndefined();
});
it('应该拒绝无效邮箱', async () => {
const request: UserRegistrationRequest = {
email: 'invalid-email',
fullName: 'Test User',
};
const result = await service.registerUser(request);
expect(result.success).toBe(false);
expect(result.error).toContain('邮箱格式无效');
});
it('应该拒绝空邮箱', async () => {
const request: UserRegistrationRequest = {
email: '',
fullName: 'Test User',
};
const result = await service.registerUser(request);
expect(result.success).toBe(false);
expect(result.error).toContain('邮箱不能为空');
});
it('应该拒绝空用户名', async () => {
const request: UserRegistrationRequest = {
email: 'test@example.com',
fullName: '',
};
const result = await service.registerUser(request);
expect(result.success).toBe(false);
expect(result.error).toContain('用户全名不能为空');
});
it('应该拒绝过短的用户名', async () => {
const request: UserRegistrationRequest = {
email: 'test@example.com',
fullName: 'A',
};
const result = await service.registerUser(request);
expect(result.success).toBe(false);
expect(result.error).toContain('用户全名至少需要2个字符');
});
it('应该拒绝过长的用户名', async () => {
const request: UserRegistrationRequest = {
email: 'test@example.com',
fullName: 'A'.repeat(101), // 101个字符
};
const result = await service.registerUser(request);
expect(result.success).toBe(false);
expect(result.error).toContain('用户全名不能超过100个字符');
});
it('应该拒绝过短的密码', async () => {
const request: UserRegistrationRequest = {
email: 'test@example.com',
fullName: 'Test User',
password: '123', // 只有3个字符
};
const result = await service.registerUser(request);
expect(result.success).toBe(false);
expect(result.error).toContain('密码至少需要6个字符');
});
it('应该接受没有密码的注册', async () => {
const request: UserRegistrationRequest = {
email: 'test@example.com',
fullName: 'Test User',
// 不提供密码
};
const result = await service.registerUser(request);
expect(result.success).toBe(true);
});
it('应该拒绝过长的短名称', async () => {
const request: UserRegistrationRequest = {
email: 'test@example.com',
fullName: 'Test User',
shortName: 'A'.repeat(51), // 51个字符
};
const result = await service.registerUser(request);
expect(result.success).toBe(false);
expect(result.error).toContain('短名称不能超过50个字符');
});
});
});