Files
oidc-client-rx/src/login/par/par-login.service.spec.ts
2025-02-02 00:45:46 +08:00

483 lines
15 KiB
TypeScript

import { TestBed, spyOnProperty } from '@/testing';
import { firstValueFrom, of } from 'rxjs';
import { vi } from 'vitest';
import { CheckAuthService } from '../../auth-state/check-auth.service';
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
import { LoggerService } from '../../logging/logger.service';
import { mockProvider } from '../../testing/mock';
import { RedirectService } from '../../utils/redirect/redirect.service';
import { UrlService } from '../../utils/url/url.service';
import type { LoginResponse } from '../login-response';
import type { PopupResult } from '../popup/popup-result';
import { PopUpService } from '../popup/popup.service';
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
import { ParLoginService } from './par-login.service';
import type { ParResponse } from './par-response';
import { ParService } from './par.service';
describe('ParLoginService', () => {
let service: ParLoginService;
let responseTypeValidationService: ResponseTypeValidationService;
let loggerService: LoggerService;
let authWellKnownService: AuthWellKnownService;
let parService: ParService;
let urlService: UrlService;
let redirectService: RedirectService;
let popupService: PopUpService;
let checkAuthService: CheckAuthService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
ParLoginService,
mockProvider(LoggerService),
mockProvider(ResponseTypeValidationService),
mockProvider(UrlService),
mockProvider(RedirectService),
mockProvider(AuthWellKnownService),
mockProvider(PopUpService),
mockProvider(CheckAuthService),
mockProvider(ParService),
],
});
service = TestBed.inject(ParLoginService);
loggerService = TestBed.inject(LoggerService);
responseTypeValidationService = TestBed.inject(
ResponseTypeValidationService
);
authWellKnownService = TestBed.inject(AuthWellKnownService);
parService = TestBed.inject(ParService);
urlService = TestBed.inject(UrlService);
redirectService = TestBed.inject(RedirectService);
popupService = TestBed.inject(PopUpService);
checkAuthService = TestBed.inject(CheckAuthService);
});
it('should create', () => {
expect(service).toBeTruthy();
});
describe('loginPar', () => {
it('does nothing if it has an invalid response type', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(false);
const loggerSpy = vi.spyOn(loggerService, 'logError');
const result = await firstValueFrom(service.loginPar({}));
expect(result).toBeUndefined();
expect(loggerSpy).toHaveBeenCalled();
});
it('calls parService.postParRequest without custom params when no custom params are passed', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
const spy = vi
.spyOn(parService, 'postParRequest')
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
const result = await firstValueFrom(
service.loginPar({
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
})
);
expect(result).toBeUndefined();
expect(spy).toHaveBeenCalled();
});
it('calls parService.postParRequest with custom params when custom params are passed', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
const spy = vi
.spyOn(parService, 'postParRequest')
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
const result = await firstValueFrom(
service.loginPar(config, {
customParams: { some: 'thing' },
})
);
expect(result).toBeUndefined();
expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
customParams: { some: 'thing' },
});
});
it('returns undefined and logs error when no url could be created', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue('');
const spy = vi.spyOn(loggerService, 'logError');
const result = await firstValueFrom(service.loginPar(config));
expect(result).toBeUndefined();
expect(spy).toHaveBeenCalledTimes(1);
});
it('calls redirect service redirectTo when url could be created', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
const authOptions = {};
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
'some-par-url'
);
const spy = vi.spyOn(redirectService, 'redirectTo');
await firstValueFrom(service.loginPar(config, authOptions));
expect(spy).toHaveBeenCalledExactlyOnceWith('some-par-url');
});
it('calls urlHandler when URL is passed', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
'some-par-url'
);
const redirectToSpy = vi.spyOn(redirectService, 'redirectTo');
const spy = vi.fn();
const urlHandler = (url: any): void => {
spy(url);
};
await firstValueFrom(service.loginPar(config, { urlHandler }));
expect(spy).toHaveBeenCalledExactlyOnceWith('some-par-url');
expect(redirectToSpy).not.toHaveBeenCalled();
});
});
describe('loginWithPopUpPar', () => {
it('does nothing if it has an invalid response type', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(false);
const loggerSpy = vi.spyOn(loggerService, 'logError');
const config = {};
const allConfigs = [config];
try {
await firstValueFrom(service.loginWithPopUpPar(config, allConfigs));
} catch (err: any) {
expect(loggerSpy).toHaveBeenCalled();
expect(err.message).toBe('Invalid response type!');
}
});
it('calls parService.postParRequest without custom params when no custom params are passed', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
const allConfigs = [config];
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
const spy = vi
.spyOn(parService, 'postParRequest')
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
try {
await firstValueFrom(service.loginWithPopUpPar(config, allConfigs));
} catch (err: any) {
expect(spy).toHaveBeenCalled();
expect(err.message).toBe(
"Could not create URL with param requestUri: 'url'"
);
}
});
it('calls parService.postParRequest with custom params when custom params are passed', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
const allConfigs = [config];
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
const spy = vi
.spyOn(parService, 'postParRequest')
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
try {
await firstValueFrom(
service.loginWithPopUpPar(config, allConfigs, {
customParams: { some: 'thing' },
})
);
} catch (err: any) {
expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
customParams: { some: 'thing' },
});
expect(err.message).toBe(
"Could not create URL with param requestUri: 'url'"
);
}
});
it('returns undefined and logs error when no URL could be created', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
const allConfigs = [config];
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue('');
const spy = vi.spyOn(loggerService, 'logError');
try {
await firstValueFrom(
service.loginWithPopUpPar(config, allConfigs, {
customParams: { some: 'thing' },
})
);
} catch (err: any) {
expect(err.message).toBe(
"Could not create URL with param requestUri: 'url'"
);
expect(spy).toHaveBeenCalledTimes(1);
}
});
it('calls popupService openPopUp when URL could be created', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
};
const allConfigs = [config];
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
'some-par-url'
);
vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue(
of({} as LoginResponse)
);
spyOnProperty(popupService, 'result$').mockReturnValue(
of({} as PopupResult)
);
const spy = vi.spyOn(popupService, 'openPopUp');
await firstValueFrom(service.loginWithPopUpPar(config, allConfigs));
expect(spy).toHaveBeenCalledExactlyOnceWith(
'some-par-url',
undefined,
config
);
});
it('returns correct properties if URL is received', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
configId: 'configId1',
};
const allConfigs = [config];
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
'some-par-url'
);
const checkAuthSpy = vi
.spyOn(checkAuthService, 'checkAuth')
.mockReturnValue(
of({
isAuthenticated: true,
configId: 'configId1',
idToken: '',
userData: { any: 'userData' },
accessToken: 'anyAccessToken',
})
);
const popupResult: PopupResult = {
userClosed: false,
receivedUrl: 'someUrl',
};
spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
const result = await firstValueFrom(
service.loginWithPopUpPar(config, allConfigs)
);
expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith(
config,
allConfigs,
'someUrl'
);
expect(result).toEqual({
isAuthenticated: true,
configId: 'configId1',
idToken: '',
userData: { any: 'userData' },
accessToken: 'anyAccessToken',
});
});
it('returns correct properties if popup was closed by user', async () => {
vi.spyOn(
responseTypeValidationService,
'hasConfigValidResponseType'
).mockReturnValue(true);
const config = {
authWellknownEndpointUrl: 'authWellknownEndpoint',
responseType: 'stubValue',
configId: 'configId1',
};
const allConfigs = [config];
vi.spyOn(
authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({}));
vi.spyOn(parService, 'postParRequest').mockReturnValue(
of({ requestUri: 'requestUri' } as ParResponse)
);
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
'some-par-url'
);
const checkAuthSpy = vi.spyOn(checkAuthService, 'checkAuth');
const popupResult = { userClosed: true } as PopupResult;
spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
const result = await firstValueFrom(
service.loginWithPopUpPar(config, allConfigs)
);
expect(checkAuthSpy).not.toHaveBeenCalled();
expect(result).toEqual({
isAuthenticated: false,
errorMessage: 'User closed popup',
configId: 'configId1',
idToken: '',
userData: null,
accessToken: '',
});
});
});
});