import { DyNTS_OAuth2_Controller } from './oauth2.controller'; import { DyNTS_Endpoint_Params } from '../../../_models/control-models/endpoint-params.control-model'; import { DyFM_HttpCallType } from '@futdevpro/fsm-dynamo'; import { DyNTS_OAuth2_AuthService } from '../_services/oauth2.auth-service'; import { DyNTS_OAuth2_ControlService } from '../_services/oauth2.control-service'; describe('| DyNTS_OAuth2_Controller', () => { let controller: DyNTS_OAuth2_Controller; let mockAuthService: jasmine.SpyObj; let mockControlService: jasmine.SpyObj; beforeEach(() => { // Reset singleton instances to prevent state leakage between tests (DyNTS_OAuth2_Controller as any).instance = undefined; (DyNTS_OAuth2_ControlService as any).instance = undefined; (DyNTS_OAuth2_AuthService as any).instance = undefined; // Mock the services to prevent circular dependency mockAuthService = jasmine.createSpyObj('DyNTS_OAuth2_AuthService', [ 'authenticate_token', 'getTokenFromRequest', ]); mockControlService = jasmine.createSpyObj('DyNTS_OAuth2_ControlService', [ 'handleAuthorizationRequest', 'handleTokenRequest', 'handleUserInfoRequest', 'handleTokenRevocation', ]); spyOn(DyNTS_OAuth2_AuthService, 'getInstance').and.returnValue(mockAuthService); spyOn(DyNTS_OAuth2_ControlService, 'getInstance').and.returnValue(mockControlService); // Now we can safely get the Controller instance controller = DyNTS_OAuth2_Controller.getInstance(); // Replace the services with our mocks (controller as any).authService = mockAuthService; (controller as any).controlService = mockControlService; }); it('| should be a singleton instance', () => { const instance1 = DyNTS_OAuth2_Controller.getInstance(); const instance2 = DyNTS_OAuth2_Controller.getInstance(); expect(instance1).toBe(instance2); expect(instance1).toBeInstanceOf(DyNTS_OAuth2_Controller); }); describe('| setupEndpoints', () => { it('| should setup all OAuth2 endpoints', () => { controller.setupEndpoints(); expect(controller.endpoints).toBeDefined(); expect(controller.endpoints.length).toBe(4); }); it('| should setup authorize endpoint', () => { controller.setupEndpoints(); const authorizeEndpoint = controller.endpoints.find(ep => ep.name === 'authorize'); expect(authorizeEndpoint).toBeDefined(); expect(authorizeEndpoint?.type).toBe(DyFM_HttpCallType.get); expect(authorizeEndpoint?.endpoint).toBe('/oauth2/authorize'); expect((authorizeEndpoint as any)?.tasks).toBeDefined(); expect((authorizeEndpoint as any)?.tasks?.length).toBe(1); }); it('| should setup token endpoint', () => { controller.setupEndpoints(); const tokenEndpoint = controller.endpoints.find(ep => ep.name === 'token'); expect(tokenEndpoint).toBeDefined(); expect(tokenEndpoint?.type).toBe(DyFM_HttpCallType.post); expect(tokenEndpoint?.endpoint).toBe('/oauth2/token'); expect((tokenEndpoint as any)?.tasks).toBeDefined(); expect((tokenEndpoint as any)?.tasks?.length).toBe(1); }); it('| should setup userinfo endpoint', () => { controller.setupEndpoints(); const userinfoEndpoint = controller.endpoints.find(ep => ep.name === 'userinfo'); expect(userinfoEndpoint).toBeDefined(); expect(userinfoEndpoint?.type).toBe(DyFM_HttpCallType.get); expect(userinfoEndpoint?.endpoint).toBe('/oauth2/userinfo'); expect((userinfoEndpoint as any)?.preProcesses).toBeDefined(); expect((userinfoEndpoint as any)?.preProcesses?.length).toBe(1); expect((userinfoEndpoint as any)?.tasks).toBeDefined(); expect((userinfoEndpoint as any)?.tasks?.length).toBe(1); }); it('| should setup revoke endpoint', () => { controller.setupEndpoints(); const revokeEndpoint = controller.endpoints.find(ep => ep.name === 'revoke'); expect(revokeEndpoint).toBeDefined(); expect(revokeEndpoint?.type).toBe(DyFM_HttpCallType.post); expect(revokeEndpoint?.endpoint).toBe('/oauth2/revoke'); expect((revokeEndpoint as any)?.preProcesses).toBeDefined(); expect((revokeEndpoint as any)?.preProcesses?.length).toBe(1); expect((revokeEndpoint as any)?.tasks).toBeDefined(); expect((revokeEndpoint as any)?.tasks?.length).toBe(1); }); }); });