import { describe, it, expect, vi, beforeEach } from 'vitest'; import { ForgotPasswordPageQuery } from './ForgotPasswordPageQuery'; import { AuthPageService } from '@/lib/services/auth/AuthPageService'; import { Result } from '@/lib/contracts/Result'; import { ForgotPasswordViewDataBuilder } from '@/lib/builders/view-data/ForgotPasswordViewDataBuilder'; import { SearchParamParser } from '@/lib/routing/search-params/SearchParamParser'; // Mock dependencies const mockProcessForgotPasswordParams = vi.fn(); const mockProcessLoginParams = vi.fn(); const mockProcessResetPasswordParams = vi.fn(); const mockProcessSignupParams = vi.fn(); vi.mock('@/lib/services/auth/AuthPageService', () => { return { AuthPageService: class { processForgotPasswordParams = mockProcessForgotPasswordParams; processLoginParams = mockProcessLoginParams; processResetPasswordParams = mockProcessResetPasswordParams; processSignupParams = mockProcessSignupParams; }, }; }); vi.mock('@/lib/routing/search-params/SearchParamParser', () => ({ SearchParamParser: { parseAuth: vi.fn(), }, })); vi.mock('@/lib/builders/view-data/ForgotPasswordViewDataBuilder', () => ({ ForgotPasswordViewDataBuilder: { build: vi.fn(), }, })); describe('ForgotPasswordPageQuery', () => { let query: ForgotPasswordPageQuery; let mockServiceInstance: any; let mockSearchParams: URLSearchParams; beforeEach(() => { vi.clearAllMocks(); mockServiceInstance = { processForgotPasswordParams: mockProcessForgotPasswordParams, }; query = new ForgotPasswordPageQuery(mockServiceInstance as any); mockSearchParams = new URLSearchParams('returnTo=/login&token=xyz789'); }); it('should return view data when search params are valid and service succeeds', async () => { const parsedParams = { returnTo: '/login', token: 'xyz789' }; const serviceOutput = { email: 'test@example.com' }; const viewData = { email: 'test@example.com', returnTo: '/login' }; (SearchParamParser.parseAuth as any).mockReturnValue(Result.ok(parsedParams)); mockServiceInstance.processForgotPasswordParams.mockResolvedValue(Result.ok(serviceOutput)); (ForgotPasswordViewDataBuilder.build as any).mockReturnValue(viewData); const result = await query.execute(mockSearchParams); expect(result.isOk()).toBe(true); expect(result.unwrap()).toEqual(viewData); expect(SearchParamParser.parseAuth).toHaveBeenCalledWith(mockSearchParams); expect(mockServiceInstance.processForgotPasswordParams).toHaveBeenCalledWith(parsedParams); expect(ForgotPasswordViewDataBuilder.build).toHaveBeenCalledWith(serviceOutput); }); it('should return error when search params are invalid', async () => { (SearchParamParser.parseAuth as any).mockReturnValue(Result.err('Invalid params')); const result = await query.execute(mockSearchParams); expect(result.isErr()).toBe(true); expect(result.getError()).toBe('Invalid search parameters: Invalid params'); }); it('should return error when service fails', async () => { const parsedParams = { returnTo: '/login', token: 'xyz789' }; (SearchParamParser.parseAuth as any).mockReturnValue(Result.ok(parsedParams)); mockServiceInstance.processForgotPasswordParams.mockResolvedValue( Result.err({ message: 'Service error' }) ); const result = await query.execute(mockSearchParams); expect(result.isErr()).toBe(true); expect(result.getError()).toBe('Service error'); }); it('should return error on exception', async () => { const parsedParams = { returnTo: '/login', token: 'xyz789' }; (SearchParamParser.parseAuth as any).mockReturnValue(Result.ok(parsedParams)); mockServiceInstance.processForgotPasswordParams.mockRejectedValue(new Error('Unexpected error')); const result = await query.execute(mockSearchParams); expect(result.isErr()).toBe(true); expect(result.getError()).toBe('Unexpected error'); }); it('should provide a static execute method', async () => { const parsedParams = { returnTo: '/login', token: 'xyz789' }; const serviceOutput = { email: 'test@example.com' }; const viewData = { email: 'test@example.com', returnTo: '/login' }; (SearchParamParser.parseAuth as any).mockReturnValue(Result.ok(parsedParams)); mockServiceInstance.processForgotPasswordParams.mockResolvedValue(Result.ok(serviceOutput)); (ForgotPasswordViewDataBuilder.build as any).mockReturnValue(viewData); const result = await ForgotPasswordPageQuery.execute(mockSearchParams); expect(result.isOk()).toBe(true); expect(result.unwrap()).toEqual(viewData); }); it('should handle Record input', async () => { const recordParams = { returnTo: '/login', token: 'xyz789' }; const parsedParams = { returnTo: '/login', token: 'xyz789' }; const serviceOutput = { email: 'test@example.com' }; const viewData = { email: 'test@example.com', returnTo: '/login' }; (SearchParamParser.parseAuth as any).mockReturnValue(Result.ok(parsedParams)); mockServiceInstance.processForgotPasswordParams.mockResolvedValue(Result.ok(serviceOutput)); (ForgotPasswordViewDataBuilder.build as any).mockReturnValue(viewData); const result = await query.execute(recordParams); expect(result.isOk()).toBe(true); expect(result.unwrap()).toEqual(viewData); expect(SearchParamParser.parseAuth).toHaveBeenCalledWith(recordParams); }); });