import { CreateDeckCommandHandler } from '../../../../src/Application/Deck/commands/CreateDeckCommandHandler'; import { CreateDeckCommand } from '../../../../src/Application/Deck/commands/CreateDeckCommand'; import { IDeckRepository } from '../../../../src/Domain/IRepository/IDeckRepository'; import { IUserRepository } from '../../../../src/Domain/IRepository/IUserRepository'; import { IOrganizationRepository } from '../../../../src/Domain/IRepository/IOrganizationRepository'; import { UserState } from '../../../../src/Domain/User/UserAggregate'; import { Type as DeckType } from '../../../../src/Domain/Deck/DeckAggregate'; import { createMockDeck, createMockDeckRepository, createMockUserRepository, createMockOrganizationRepository, createMockUser } from '../../../testUtils'; describe('CreateDeckCommandHandler', () => { let handler: CreateDeckCommandHandler; let mockDeckRepository: jest.Mocked; let mockUserRepository: jest.Mocked; let mockOrganizationRepository: jest.Mocked; beforeEach(() => { jest.clearAllMocks(); mockDeckRepository = createMockDeckRepository(); mockUserRepository = createMockUserRepository(); mockOrganizationRepository = createMockOrganizationRepository(); handler = new CreateDeckCommandHandler(mockDeckRepository, mockUserRepository, mockOrganizationRepository); }); describe('execute', () => { it('should successfully create a new deck with valid user', async () => { // Arrange const command: CreateDeckCommand = { name: 'Test Deck', type: DeckType.JOKER, userid: 'user-123', cards: [{ id: 'card-1', name: 'Test Card' }], }; const mockUser = createMockUser({ id: command.userid, state: UserState.VERIFIED_REGULAR, type: 'user' }); const mockDeck = createMockDeck({ name: command.name, type: command.type, userid: command.userid }); mockUserRepository.findById.mockResolvedValue(mockUser); mockDeckRepository.countActiveByUserId.mockResolvedValue(0); mockDeckRepository.create.mockResolvedValue(mockDeck); // Act const result = await handler.execute(command); // Assert expect(result).toBeDefined(); expect(mockUserRepository.findById).toHaveBeenCalledWith(command.userid); expect(mockDeckRepository.create).toHaveBeenCalled(); }); it('should throw error when user not found', async () => { // Arrange const command: CreateDeckCommand = { name: 'Test Deck', type: DeckType.JOKER, userid: 'nonexistent-user', cards: [], }; mockUserRepository.findById.mockResolvedValue(null); // Act & Assert await expect(handler.execute(command)).rejects.toThrow('User not found'); expect(mockUserRepository.findById).toHaveBeenCalledWith(command.userid); expect(mockDeckRepository.create).not.toHaveBeenCalled(); }); it('should handle admin user creating unlimited decks', async () => { // Arrange const command: CreateDeckCommand = { name: 'Admin Deck', type: DeckType.JOKER, userid: 'admin-123', cards: [], }; const mockAdminUser = createMockUser({ id: command.userid, state: UserState.VERIFIED_REGULAR, type: 'admin' }); const mockDeck = createMockDeck({ name: command.name, type: command.type, userid: command.userid }); mockUserRepository.findById.mockResolvedValue(mockAdminUser); mockDeckRepository.create.mockResolvedValue(mockDeck); // Act const result = await handler.execute(command); // Assert expect(result).toBeDefined(); expect(mockDeckRepository.countActiveByUserId).toHaveBeenCalled(); // Admin still checks but bypasses limits }); it('should handle repository creation errors', async () => { // Arrange const command: CreateDeckCommand = { name: 'Test Deck', type: DeckType.JOKER, userid: 'user-123', cards: [], }; const mockUser = createMockUser({ id: command.userid }); mockUserRepository.findById.mockResolvedValue(mockUser); mockDeckRepository.countActiveByUserId.mockResolvedValue(0); mockDeckRepository.create.mockRejectedValue(new Error('Database error')); // Act & Assert await expect(handler.execute(command)).rejects.toThrow('Database error'); }); it('should create deck with different types', async () => { // Arrange const command: CreateDeckCommand = { name: 'Question Deck', type: DeckType.QUESTION, userid: 'user-123', cards: [], }; const mockUser = createMockUser({ id: command.userid }); const mockDeck = createMockDeck({ name: command.name, type: command.type, userid: command.userid }); mockUserRepository.findById.mockResolvedValue(mockUser); mockDeckRepository.countActiveByUserId.mockResolvedValue(0); mockDeckRepository.create.mockResolvedValue(mockDeck); // Act const result = await handler.execute(command); // Assert expect(result).toBeDefined(); expect(mockDeckRepository.create).toHaveBeenCalledWith(expect.objectContaining({ type: DeckType.QUESTION })); }); it('should handle empty cards array', async () => { // Arrange const command: CreateDeckCommand = { name: 'Empty Deck', type: DeckType.JOKER, userid: 'user-123', cards: [], }; const mockUser = createMockUser({ id: command.userid }); const mockDeck = createMockDeck(command); mockUserRepository.findById.mockResolvedValue(mockUser); mockDeckRepository.countActiveByUserId.mockResolvedValue(0); mockDeckRepository.create.mockResolvedValue(mockDeck); // Act const result = await handler.execute(command); // Assert expect(result).toBeDefined(); }); it('should check deck limits for regular users', async () => { // Arrange const command: CreateDeckCommand = { name: 'Test Deck', type: DeckType.JOKER, userid: 'user-123', cards: [], }; const mockUser = createMockUser({ id: command.userid, type: 'user' }); const mockDeck = createMockDeck({ userid: command.userid }); mockUserRepository.findById.mockResolvedValue(mockUser); mockDeckRepository.countActiveByUserId.mockResolvedValue(0); mockDeckRepository.create.mockResolvedValue(mockDeck); // Act await handler.execute(command); // Assert expect(mockDeckRepository.countActiveByUserId).toHaveBeenCalledWith(command.userid); }); }); });