forked from datawhale/whale-town-end
feat: 添加JWT认证系统和Zulip用户管理服务
- 新增JWT认证守卫(JwtAuthGuard)和当前用户装饰器(CurrentUser) - 添加JWT使用示例和完整的认证流程文档 - 实现Zulip用户管理服务,支持用户查询、验证和管理 - 实现Zulip用户注册服务,支持新用户创建和注册流程 - 添加完整的单元测试覆盖 - 新增真实环境测试脚本,验证Zulip API集成 - 更新.gitignore,排除.kiro目录 主要功能: - JWT令牌验证和用户信息提取 - 用户存在性检查和信息获取 - Zulip API集成和错误处理 - 完整的测试覆盖和文档
This commit is contained in:
188
src/core/zulip/services/user_registration.service.spec.ts
Normal file
188
src/core/zulip/services/user_registration.service.spec.ts
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* 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个字符');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user