UNPKG

matterbridge-roborock-vacuum-plugin

Version:
149 lines 9.06 kB
import { beforeEach, describe, expect, it, vi } from 'vitest'; import { AuthenticationCoordinator } from '../../../services/authentication/AuthenticationCoordinator.js'; import { asPartial, createMockLogger } from '../../testUtils.js'; describe('AuthenticationCoordinator', () => { let coordinator; let mockPasswordStrategy; let mockTwoFactorStrategy; let mockLogger; const mockUserData = asPartial({ uid: 'user123', username: 'test@example.com', token: 'valid-token', tokentype: 'Bearer', region: 'us', }); beforeEach(() => { mockLogger = createMockLogger(); mockPasswordStrategy = asPartial({ authenticate: vi.fn(), }); mockTwoFactorStrategy = asPartial({ authenticate: vi.fn(), }); coordinator = new AuthenticationCoordinator(mockPasswordStrategy, mockTwoFactorStrategy, mockLogger); vi.clearAllMocks(); }); describe('authenticate', () => { const createContext = (username, password, verificationCode) => ({ username, password, verificationCode, }); describe('Password authentication', () => { it('should authenticate successfully with Password method', async () => { const context = createContext('test@example.com', 'password123'); vi.mocked(mockPasswordStrategy.authenticate).mockResolvedValue(mockUserData); const result = await coordinator.authenticate('Password', context); expect(result).toEqual(mockUserData); expect(mockPasswordStrategy.authenticate).toHaveBeenCalledWith(context); expect(mockPasswordStrategy.authenticate).toHaveBeenCalledTimes(1); }); it('should return undefined when Password strategy returns undefined', async () => { const context = createContext('test@example.com', 'wrong-password'); vi.mocked(mockPasswordStrategy.authenticate).mockResolvedValue(undefined); const result = await coordinator.authenticate('Password', context); expect(result).toBeUndefined(); expect(mockPasswordStrategy.authenticate).toHaveBeenCalledWith(context); }); it('should not call TwoFactorStrategy when using Password method', async () => { const context = createContext('test@example.com', 'password123'); vi.mocked(mockPasswordStrategy.authenticate).mockResolvedValue(mockUserData); await coordinator.authenticate('Password', context); expect(mockTwoFactorStrategy.authenticate).not.toHaveBeenCalled(); }); }); describe('VerificationCode authentication', () => { it('should authenticate successfully with VerificationCode method', async () => { const context = createContext('test@example.com', 'password123', '123456'); vi.mocked(mockTwoFactorStrategy.authenticate).mockResolvedValue(mockUserData); const result = await coordinator.authenticate('VerificationCode', context); expect(result).toEqual(mockUserData); expect(mockTwoFactorStrategy.authenticate).toHaveBeenCalledWith(context); expect(mockTwoFactorStrategy.authenticate).toHaveBeenCalledTimes(1); }); it('should return undefined when VerificationCode strategy returns undefined', async () => { const context = createContext('test@example.com', 'password123', 'wrong-code'); vi.mocked(mockTwoFactorStrategy.authenticate).mockResolvedValue(undefined); const result = await coordinator.authenticate('VerificationCode', context); expect(result).toBeUndefined(); expect(mockTwoFactorStrategy.authenticate).toHaveBeenCalledWith(context); }); it('should not call PasswordStrategy when using VerificationCode method', async () => { const context = createContext('test@example.com', 'password123', '123456'); vi.mocked(mockTwoFactorStrategy.authenticate).mockResolvedValue(mockUserData); await coordinator.authenticate('VerificationCode', context); expect(mockPasswordStrategy.authenticate).not.toHaveBeenCalled(); }); }); describe('Unknown method handling', () => { it('should throw error for unknown authentication method', async () => { const context = createContext('test@example.com', 'password123'); await expect(coordinator.authenticate('UnknownMethod', context)).rejects.toThrow('Unknown authentication method: UnknownMethod'); }); it('should log error with available methods for unknown method', async () => { const context = createContext('test@example.com', 'password123'); try { await coordinator.authenticate('InvalidMethod', context); } catch { // Expected to throw } expect(mockLogger.error).toHaveBeenCalledWith('Unknown authentication method: InvalidMethod. Available methods: Password, VerificationCode'); }); it('should not call any strategy for unknown method', async () => { const context = createContext('test@example.com', 'password123'); try { await coordinator.authenticate('BadMethod', context); } catch { // Expected to throw } expect(mockPasswordStrategy.authenticate).not.toHaveBeenCalled(); expect(mockTwoFactorStrategy.authenticate).not.toHaveBeenCalled(); }); it('should throw for empty string method', async () => { const context = createContext('test@example.com', 'password123'); await expect(coordinator.authenticate('', context)).rejects.toThrow('Unknown authentication method: '); }); it('should throw for case-sensitive method mismatch', async () => { const context = createContext('test@example.com', 'password123'); await expect(coordinator.authenticate('password', context)).rejects.toThrow('Unknown authentication method: password'); }); }); describe('Strategy delegation', () => { it('should pass context correctly to Password strategy', async () => { const context = createContext('user@test.com', 'my-password'); vi.mocked(mockPasswordStrategy.authenticate).mockResolvedValue(mockUserData); await coordinator.authenticate('Password', context); expect(mockPasswordStrategy.authenticate).toHaveBeenCalledWith(context); const calledContext = vi.mocked(mockPasswordStrategy.authenticate).mock.calls[0][0]; expect(calledContext.username).toBe('user@test.com'); expect(calledContext.password).toBe('my-password'); }); it('should pass context correctly to VerificationCode strategy', async () => { const context = createContext('user@test.com', 'my-password', '654321'); vi.mocked(mockTwoFactorStrategy.authenticate).mockResolvedValue(mockUserData); await coordinator.authenticate('VerificationCode', context); expect(mockTwoFactorStrategy.authenticate).toHaveBeenCalledWith(context); const calledContext = vi.mocked(mockTwoFactorStrategy.authenticate).mock.calls[0][0]; expect(calledContext.username).toBe('user@test.com'); expect(calledContext.password).toBe('my-password'); expect(calledContext.verificationCode).toBe('654321'); }); it('should propagate errors from Password strategy', async () => { const context = createContext('test@example.com', 'password123'); const strategyError = new Error('Password strategy failed'); vi.mocked(mockPasswordStrategy.authenticate).mockRejectedValue(strategyError); await expect(coordinator.authenticate('Password', context)).rejects.toThrow('Password strategy failed'); }); it('should propagate errors from VerificationCode strategy', async () => { const context = createContext('test@example.com', 'password123', '123456'); const strategyError = new Error('2FA strategy failed'); vi.mocked(mockTwoFactorStrategy.authenticate).mockRejectedValue(strategyError); await expect(coordinator.authenticate('VerificationCode', context)).rejects.toThrow('2FA strategy failed'); }); }); }); }); //# sourceMappingURL=AuthenticationCoordinator.test.js.map