fix: fix all biome
This commit is contained in:
parent
316361bd3c
commit
c9d0066d64
@ -4,19 +4,24 @@
|
||||
"linter": {
|
||||
"rules": {
|
||||
"style": {
|
||||
"noNonNullAssertion": "off"
|
||||
"noNonNullAssertion": "off",
|
||||
"noParameterAssign": "off",
|
||||
"useFilenamingConvention": "warn"
|
||||
},
|
||||
"suspicious": {
|
||||
"noExplicitAny": "off"
|
||||
},
|
||||
"complexity": {
|
||||
"noForEach": "info"
|
||||
"noForEach": "off"
|
||||
},
|
||||
"correctness": {
|
||||
"noUnusedImports": {
|
||||
"fix": "none",
|
||||
"level": "warn"
|
||||
}
|
||||
},
|
||||
"nursery": {
|
||||
"noEnum": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -3,8 +3,8 @@ import { describe, it } from 'node:test';
|
||||
import { Biome, Distribution } from '@biomejs/js-api';
|
||||
import { rewriteObservableSubscribeToLastValueFrom } from './code-transform';
|
||||
|
||||
describe('writeAllSpecObservableSubscribeToLastValueFrom', () => {
|
||||
it('should transform valid string', async () => {
|
||||
describe('rewriteSpecObservableSubscribeToLastValueFrom', () => {
|
||||
it('should transform simple example valid string', async () => {
|
||||
const actual = await rewriteObservableSubscribeToLastValueFrom(
|
||||
'index.ts',
|
||||
`refreshSessionIframeService
|
||||
@ -32,4 +32,51 @@ describe('writeAllSpecObservableSubscribeToLastValueFrom', () => {
|
||||
biome.formatContent(expect, { filePath: 'index.ts' }).content
|
||||
);
|
||||
});
|
||||
|
||||
it('should rewrite complex exmaple to valid string', async () => {
|
||||
const actual = await rewriteObservableSubscribeToLastValueFrom(
|
||||
'index.ts',
|
||||
`codeFlowCallbackService
|
||||
.authenticatedCallbackWithCode('some-url4', config, [config])
|
||||
.subscribe({
|
||||
error: (err: any) => {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(resetCodeFlowInProgressSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
next: (abc) => {
|
||||
expect(abc).toBeTruthy();
|
||||
},
|
||||
complete () {
|
||||
expect.fail('complete')
|
||||
}
|
||||
});`
|
||||
);
|
||||
|
||||
const expect = `
|
||||
try {
|
||||
const abc = await lastValueFrom(codeFlowCallbackService.authenticatedCallbackWithCode('some-url4', config, [config]));
|
||||
expect(abc).toBeTruthy();
|
||||
} catch (err: any) {
|
||||
if (err instanceof EmptyError) {
|
||||
expect.fail('complete')
|
||||
} else {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(resetCodeFlowInProgressSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const biome = await Biome.create({
|
||||
distribution: Distribution.NODE,
|
||||
});
|
||||
|
||||
assert.equal(
|
||||
biome.formatContent(actual, { filePath: 'index.ts' }).content,
|
||||
biome.formatContent(expect, { filePath: 'index.ts' }).content
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -1,11 +1,18 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import fsp from 'node:fs/promises';
|
||||
import { type MagicString, type Statement, parseSync } from 'oxc-parser';
|
||||
import { type Node, walk } from 'oxc-walker';
|
||||
import {
|
||||
type ArrowFunctionExpression,
|
||||
// biome-ignore lint/suspicious/noShadowRestrictedNames: <explanation>
|
||||
type Function,
|
||||
type MagicString,
|
||||
type Statement,
|
||||
parseSync,
|
||||
} from 'oxc-parser';
|
||||
import { walk } from 'oxc-walker';
|
||||
|
||||
function sourceTextFromNode(
|
||||
context: { magicString?: MagicString },
|
||||
node: Node
|
||||
node: { start: number; end: number }
|
||||
): string {
|
||||
const magicString = context.magicString;
|
||||
assert(magicString, 'magicString should be defined');
|
||||
@ -33,53 +40,101 @@ export async function rewriteObservableSubscribeToLastValueFrom(
|
||||
child.type === 'ExpressionStatement' &&
|
||||
child.expression.type === 'CallExpression' &&
|
||||
child.expression.callee.type === 'StaticMemberExpression' &&
|
||||
child.expression.callee.property.name === 'subscribe' &&
|
||||
child.expression.arguments.length === 0
|
||||
child.expression.callee.property.name === 'subscribe'
|
||||
) {
|
||||
const newContent = `await lastValueFrom(${sourceTextFromNode(context, child.expression.callee.object)});`;
|
||||
let next: ArrowFunctionExpression | Function | undefined;
|
||||
let error: ArrowFunctionExpression | Function | undefined;
|
||||
let complete: ArrowFunctionExpression | Function | undefined;
|
||||
|
||||
const newStatements = parseSync('index.ts', newContent).program
|
||||
.body as any[];
|
||||
if (child.expression.arguments[0]?.type === 'ObjectExpression') {
|
||||
const obj = child.expression.arguments[0];
|
||||
for (const prop of obj.properties) {
|
||||
if (
|
||||
prop.type === 'ObjectProperty' &&
|
||||
prop.key.type === 'Identifier' &&
|
||||
(prop.value.type === 'FunctionExpression' ||
|
||||
prop.value.type === 'ArrowFunctionExpression')
|
||||
) {
|
||||
if (prop.key.name === 'next') {
|
||||
next = prop.value;
|
||||
} else if (prop.key.name === 'error') {
|
||||
error = prop.value;
|
||||
} else if (prop.key.name === 'complete') {
|
||||
complete = prop.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
child.expression.arguments.find(
|
||||
(arg) =>
|
||||
arg.type === 'FunctionExpression' ||
|
||||
arg.type === 'ArrowFunctionExpression'
|
||||
)
|
||||
) {
|
||||
const args: Array<
|
||||
Function | ArrowFunctionExpression | undefined
|
||||
> = child.expression.arguments.map((arg) =>
|
||||
arg.type === 'FunctionExpression' ||
|
||||
arg.type === 'ArrowFunctionExpression'
|
||||
? arg
|
||||
: undefined
|
||||
);
|
||||
next = args[0];
|
||||
error = args[1];
|
||||
complete = args[2];
|
||||
}
|
||||
let newContent = `await lastValueFrom(${sourceTextFromNode(context, child.expression.callee.object)});`;
|
||||
|
||||
magicString.remove(child.start, child.end);
|
||||
magicString.appendRight(child.start, newContent);
|
||||
if (next) {
|
||||
const nextParam =
|
||||
next?.params?.items?.[0]?.type === 'FormalParameter'
|
||||
? sourceTextFromNode(context, next.params.items[0])
|
||||
: undefined;
|
||||
|
||||
newChildren.push(...newStatements);
|
||||
} else if (
|
||||
child.type === 'ExpressionStatement' &&
|
||||
child.expression.type === 'CallExpression' &&
|
||||
child.expression.callee.type === 'StaticMemberExpression' &&
|
||||
child.expression.callee.property.name === 'subscribe' &&
|
||||
child.expression.arguments[0]?.type === 'ArrowFunctionExpression' &&
|
||||
child.expression.arguments[0].body.type === 'FunctionBody'
|
||||
) {
|
||||
const awaited =
|
||||
child.expression.arguments[0].params.kind ===
|
||||
'ArrowFormalParameters' &&
|
||||
child.expression.arguments[0].params.items[0]?.type ===
|
||||
'FormalParameter' &&
|
||||
child.expression.arguments[0].params.items[0].pattern.type ===
|
||||
'Identifier'
|
||||
? child.expression.arguments[0].params.items[0].pattern.name
|
||||
: undefined;
|
||||
const newContent =
|
||||
(awaited
|
||||
? `const ${awaited} = await lastValueFrom(${sourceTextFromNode(
|
||||
context,
|
||||
child.expression.callee.object
|
||||
)});\n`
|
||||
: `await lastValueFrom(${sourceTextFromNode(context, child.expression.callee.object)});\n`) +
|
||||
child.expression.arguments[0].body.statements
|
||||
if (nextParam) {
|
||||
newContent = `const ${nextParam} = ${newContent}`;
|
||||
}
|
||||
newContent += (next.body?.statements || [])
|
||||
.map((s) => sourceTextFromNode(context, s))
|
||||
.join(';\n');
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
const newStatements = parseSync('index.ts', newContent).program
|
||||
.body as any[];
|
||||
if (error || complete) {
|
||||
const errorParam =
|
||||
error?.params?.items?.[0]?.type === 'FormalParameter' &&
|
||||
error.params.items[0].pattern.type === 'Identifier'
|
||||
? sourceTextFromNode(context, error.params.items[0])
|
||||
: 'err';
|
||||
const errorParamName =
|
||||
error?.params?.items?.[0]?.type === 'FormalParameter' &&
|
||||
error.params.items[0].pattern.type === 'Identifier'
|
||||
? error.params.items[0].pattern.name
|
||||
: 'err';
|
||||
|
||||
let errorBody = '';
|
||||
if (error) {
|
||||
errorBody += (error.body?.statements || [])
|
||||
.map((s) => sourceTextFromNode(context, s))
|
||||
.join('\n');
|
||||
}
|
||||
if (complete) {
|
||||
const completBody = `if (${errorParamName} instanceof EmptyError) { ${(complete.body?.statements || []).map((s) => sourceTextFromNode(context, s)).join('\n')}}`;
|
||||
if (errorBody) {
|
||||
errorBody = `${completBody} else { ${errorBody} }`;
|
||||
} else {
|
||||
errorBody = completBody;
|
||||
}
|
||||
}
|
||||
|
||||
newContent = `try { ${newContent} } catch (${errorParam}) { ${errorBody} }`;
|
||||
}
|
||||
|
||||
const newNodes = parseSync('index.html', newContent).program.body;
|
||||
|
||||
magicString.remove(child.start, child.end);
|
||||
magicString.appendRight(child.start, newContent);
|
||||
magicString.appendLeft(child.start, newContent);
|
||||
|
||||
newChildren.push(...newStatements);
|
||||
newChildren.push(...newNodes);
|
||||
} else {
|
||||
newChildren.push(child as any);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { HttpHeaders, HttpParams } from '@ngify/http';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { HttpBaseService } from './http-base.service';
|
||||
|
||||
const NGSW_CUSTOM_PARAM = 'ngsw-bypass';
|
||||
@ -41,10 +41,10 @@ export class DataService {
|
||||
|
||||
headers = headers.set('Accept', 'application/json');
|
||||
|
||||
if (!!token) {
|
||||
if (token) {
|
||||
headers = headers.set(
|
||||
'Authorization',
|
||||
'Bearer ' + decodeURIComponent(token)
|
||||
`Bearer ${decodeURIComponent(token)}`
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { HttpClient } from '@ngify/http';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Observable } from 'rxjs';
|
||||
import type { Observable } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class HttpBaseService {
|
||||
constructor() {}
|
||||
|
||||
private readonly http = inject(HttpClient);
|
||||
|
||||
get<T>(url: string, params?: { [key: string]: unknown }): Observable<T> {
|
||||
|
@ -38,7 +38,7 @@ describe('Auth State Service', () => {
|
||||
expect(authStateService).toBeTruthy();
|
||||
});
|
||||
|
||||
it('public authorize$ is observable$', () => {
|
||||
it('authorize$ is observable$', () => {
|
||||
expect(authStateService.authenticated$).toBeInstanceOf(Observable);
|
||||
});
|
||||
|
||||
@ -269,6 +269,7 @@ describe('Auth State Service', () => {
|
||||
|
||||
it('does not crash and store accessToken when authResult is null', () => {
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
// biome-ignore lint/suspicious/noEvolvingTypes: <explanation>
|
||||
const authResult = null;
|
||||
|
||||
authStateService.setAuthorizationData(
|
||||
|
@ -257,9 +257,8 @@ export class AuthStateService {
|
||||
private decodeURIComponentSafely(token: string): string {
|
||||
if (token) {
|
||||
return decodeURIComponent(token);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private persistAccessTokenExpirationTime(
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ValidationResult } from '../validation/validation-result';
|
||||
import type { ValidationResult } from '../validation/validation-result';
|
||||
|
||||
export interface AuthStateResult {
|
||||
isAuthenticated: boolean;
|
||||
|
@ -135,12 +135,14 @@ describe('CheckAuthService', () => {
|
||||
);
|
||||
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
|
||||
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
|
||||
it('uses first/default config when no param is passed', async () => {
|
||||
@ -153,12 +155,14 @@ describe('CheckAuthService', () => {
|
||||
];
|
||||
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1', authority: 'some-authority' },
|
||||
allConfigs,
|
||||
undefined
|
||||
);
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1', authority: 'some-authority' },
|
||||
allConfigs,
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
it('returns null and sendMessageToMainWindow if currently in a popup', async () => {
|
||||
@ -180,17 +184,18 @@ expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
vi.spyOn(popUpService, 'isCurrentlyInPopup').mockReturnValue(true);
|
||||
const popupSpy = vi.spyOn(popUpService, 'sendMessageToMainWindow');
|
||||
|
||||
const result = await lastValueFrom(checkAuthService
|
||||
.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
errorMessage: '',
|
||||
userData: null,
|
||||
idToken: '',
|
||||
accessToken: '',
|
||||
configId: '',
|
||||
});;
|
||||
expect(popupSpy).toHaveBeenCalled();
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
errorMessage: '',
|
||||
userData: null,
|
||||
idToken: '',
|
||||
accessToken: '',
|
||||
configId: '',
|
||||
});
|
||||
expect(popupSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns isAuthenticated: false with error message in case handleCallbackAndFireEvents throws an error', async () => {
|
||||
@ -211,17 +216,18 @@ expect(popupSpy).toHaveBeenCalled();
|
||||
'http://localhost:4200'
|
||||
);
|
||||
|
||||
const result = await lastValueFrom(checkAuthService
|
||||
.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
errorMessage: 'ERROR',
|
||||
configId: 'configId1',
|
||||
idToken: '',
|
||||
userData: null,
|
||||
accessToken: '',
|
||||
});;
|
||||
expect(spy).toHaveBeenCalled();
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
errorMessage: 'ERROR',
|
||||
configId: 'configId1',
|
||||
idToken: '',
|
||||
userData: null,
|
||||
accessToken: '',
|
||||
});
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls callbackService.handlePossibleStsCallback with current url when callback is true', async () => {
|
||||
@ -243,16 +249,17 @@ expect(spy).toHaveBeenCalled();
|
||||
.spyOn(callBackService, 'handleCallbackAndFireEvents')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
const result = await lastValueFrom(checkAuthService
|
||||
.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: true,
|
||||
userData: undefined,
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'idt',
|
||||
});;
|
||||
expect(spy).toHaveBeenCalled();
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: true,
|
||||
userData: undefined,
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'idt',
|
||||
});
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does NOT call handleCallbackAndFireEvents with current url when callback is false', async () => {
|
||||
@ -275,16 +282,17 @@ expect(spy).toHaveBeenCalled();
|
||||
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('at');
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idt');
|
||||
|
||||
const result = await lastValueFrom(checkAuthService
|
||||
.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: true,
|
||||
userData: undefined,
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'idt',
|
||||
});;
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: true,
|
||||
userData: undefined,
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'idt',
|
||||
});
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does fire the auth and user data events when it is not a callback from the security token service and is authenticated', async () => {
|
||||
@ -314,19 +322,20 @@ expect(spy).not.toHaveBeenCalled();
|
||||
);
|
||||
const userServiceSpy = vi.spyOn(userService, 'publishUserDataIfExists');
|
||||
|
||||
const result = await lastValueFrom(checkAuthService
|
||||
.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: true,
|
||||
userData: {
|
||||
some: 'user-data',
|
||||
},
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'idt',
|
||||
});;
|
||||
expect(setAuthorizedAndFireEventSpy).toHaveBeenCalled();;
|
||||
expect(userServiceSpy).toHaveBeenCalled();
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: true,
|
||||
userData: {
|
||||
some: 'user-data',
|
||||
},
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'idt',
|
||||
});
|
||||
expect(setAuthorizedAndFireEventSpy).toHaveBeenCalled();
|
||||
expect(userServiceSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does NOT fire the auth and user data events when it is not a callback from the security token service and is NOT authenticated', async () => {
|
||||
@ -353,17 +362,18 @@ expect(userServiceSpy).toHaveBeenCalled();
|
||||
);
|
||||
const userServiceSpy = vi.spyOn(userService, 'publishUserDataIfExists');
|
||||
|
||||
const result = await lastValueFrom(checkAuthService
|
||||
.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
userData: undefined,
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'it',
|
||||
});;
|
||||
expect(setAuthorizedAndFireEventSpy).not.toHaveBeenCalled();;
|
||||
expect(userServiceSpy).not.toHaveBeenCalled();
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
userData: undefined,
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'it',
|
||||
});
|
||||
expect(setAuthorizedAndFireEventSpy).not.toHaveBeenCalled();
|
||||
expect(userServiceSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('if authenticated return true', async () => {
|
||||
@ -383,15 +393,16 @@ expect(userServiceSpy).not.toHaveBeenCalled();
|
||||
true
|
||||
);
|
||||
|
||||
const result = await lastValueFrom(checkAuthService
|
||||
.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: true,
|
||||
userData: undefined,
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'idt',
|
||||
});
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: true,
|
||||
userData: undefined,
|
||||
accessToken: 'at',
|
||||
configId: 'configId1',
|
||||
idToken: 'idt',
|
||||
});
|
||||
});
|
||||
|
||||
it('if authenticated set auth and fires event ', async () => {
|
||||
@ -409,8 +420,10 @@ expect(result).toEqual({
|
||||
|
||||
const spy = vi.spyOn(authStateService, 'setAuthenticatedAndFireEvent');
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('if authenticated publishUserdataIfExists', async () => {
|
||||
@ -430,8 +443,10 @@ expect(spy).toHaveBeenCalled();
|
||||
|
||||
const spy = vi.spyOn(userService, 'publishUserDataIfExists');
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('if authenticated callbackService startTokenValidationPeriodically', async () => {
|
||||
@ -455,8 +470,10 @@ expect(spy).toHaveBeenCalled();
|
||||
'startTokenValidationPeriodically'
|
||||
);
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('if isCheckSessionConfigured call checkSessionService.start()', async () => {
|
||||
@ -478,8 +495,10 @@ expect(spy).toHaveBeenCalled();
|
||||
);
|
||||
const spy = vi.spyOn(checkSessionService, 'start');
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('if isSilentRenewConfigured call getOrCreateIframe()', async () => {
|
||||
@ -501,8 +520,10 @@ expect(spy).toHaveBeenCalled();
|
||||
);
|
||||
const spy = vi.spyOn(silentRenewService, 'getOrCreateIframe');
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls checkSavedRedirectRouteAndNavigate if authenticated', async () => {
|
||||
@ -524,9 +545,11 @@ expect(spy).toHaveBeenCalled();
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalledTimes(1);;
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
|
||||
});
|
||||
|
||||
it('does not call checkSavedRedirectRouteAndNavigate if not authenticated', async () => {
|
||||
@ -545,8 +568,10 @@ expect(spy).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalledTimes(0);
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('fires CheckingAuth-Event on start and finished event on end', async () => {
|
||||
@ -563,11 +588,13 @@ expect(spy).toHaveBeenCalledTimes(0);
|
||||
|
||||
const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent');
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(fireEventSpy).toHaveBeenCalledWith([
|
||||
[EventTypes.CheckingAuth],
|
||||
[EventTypes.CheckingAuthFinished],
|
||||
]);
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(fireEventSpy).toHaveBeenCalledWith([
|
||||
[EventTypes.CheckingAuth],
|
||||
[EventTypes.CheckingAuthFinished],
|
||||
]);
|
||||
});
|
||||
|
||||
it('fires CheckingAuth-Event on start and CheckingAuthFinishedWithError event on end if exception occurs', async () => {
|
||||
@ -584,11 +611,13 @@ expect(fireEventSpy).toHaveBeenCalledWith([
|
||||
'http://localhost:4200'
|
||||
);
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(fireEventSpy).toHaveBeenCalledWith([
|
||||
[EventTypes.CheckingAuth],
|
||||
[EventTypes.CheckingAuthFinishedWithError, 'ERROR'],
|
||||
]);
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(fireEventSpy).toHaveBeenCalledWith([
|
||||
[EventTypes.CheckingAuth],
|
||||
[EventTypes.CheckingAuthFinishedWithError, 'ERROR'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('fires CheckingAuth-Event on start and finished event on end if not authenticated', async () => {
|
||||
@ -605,11 +634,13 @@ expect(fireEventSpy).toHaveBeenCalledWith([
|
||||
|
||||
const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent');
|
||||
|
||||
await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
|
||||
expect(fireEventSpy).toBeCalledWith([
|
||||
[EventTypes.CheckingAuth],
|
||||
[EventTypes.CheckingAuthFinished],
|
||||
]);
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(fireEventSpy).toBeCalledWith([
|
||||
[EventTypes.CheckingAuth],
|
||||
[EventTypes.CheckingAuthFinished],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -634,9 +665,10 @@ expect(fireEventSpy).toBeCalledWith([
|
||||
);
|
||||
const spy = vi.spyOn(silentRenewService, 'getOrCreateIframe');
|
||||
|
||||
await lastValueFrom(checkAuthService
|
||||
.checkAuthIncludingServer(allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuthIncludingServer(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does forceRefreshSession get called and is NOT authenticated', async () => {
|
||||
@ -662,9 +694,10 @@ expect(spy).toHaveBeenCalled();
|
||||
})
|
||||
);
|
||||
|
||||
const result = await lastValueFrom(checkAuthService
|
||||
.checkAuthIncludingServer(allConfigs[0]!, allConfigs));
|
||||
expect(result).toBeTruthy();
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuthIncludingServer(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing with silentrenew', async () => {
|
||||
@ -709,15 +742,16 @@ expect(result).toBeTruthy();
|
||||
})
|
||||
);
|
||||
|
||||
await lastValueFrom(checkAuthService
|
||||
.checkAuthIncludingServer(allConfigs[0]!, allConfigs));
|
||||
expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]
|
||||
);;
|
||||
expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1);;
|
||||
expect(getOrCreateIframeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]
|
||||
);
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuthIncludingServer(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]
|
||||
);
|
||||
expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(getOrCreateIframeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]
|
||||
);
|
||||
});
|
||||
|
||||
it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing without silentrenew', async () => {
|
||||
@ -762,13 +796,14 @@ expect(getOrCreateIframeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
})
|
||||
);
|
||||
|
||||
await lastValueFrom(checkAuthService
|
||||
.checkAuthIncludingServer(allConfigs[0]!, allConfigs));
|
||||
expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]
|
||||
);;
|
||||
expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1);;
|
||||
expect(getOrCreateIframeSpy).not.toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
checkAuthService.checkAuthIncludingServer(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]
|
||||
);
|
||||
expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(getOrCreateIframeSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@ -790,19 +825,21 @@ expect(getOrCreateIframeSpy).not.toHaveBeenCalled();
|
||||
);
|
||||
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
|
||||
|
||||
const result = await lastValueFrom(checkAuthService.checkAuthMultiple(allConfigs));
|
||||
expect(Array.isArray(result)).toBe(true);;
|
||||
expect(spy).toHaveBeenCalledTimes(2);;
|
||||
expect(vi.mocked(spy).mock.calls[0]).toEqual([
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
undefined,
|
||||
]);;
|
||||
expect(vi.mocked(spy).mock.calls[1]).toEqual([
|
||||
allConfigs[1],
|
||||
allConfigs,
|
||||
undefined,
|
||||
]);
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuthMultiple(allConfigs)
|
||||
);
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
expect(vi.mocked(spy).mock.calls[0]).toEqual([
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
undefined,
|
||||
]);
|
||||
expect(vi.mocked(spy).mock.calls[1]).toEqual([
|
||||
allConfigs[1],
|
||||
allConfigs,
|
||||
undefined,
|
||||
]);
|
||||
});
|
||||
|
||||
it('uses config from passed configId if configId was passed and returns all results', async () => {
|
||||
@ -818,20 +855,22 @@ expect(vi.mocked(spy).mock.calls[1]).toEqual([
|
||||
|
||||
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
|
||||
|
||||
const result = await lastValueFrom(checkAuthService.checkAuthMultiple(allConfigs));
|
||||
expect(Array.isArray(result)).toBe(true);;
|
||||
expect(spy).toBeCalledWith([
|
||||
[
|
||||
{ configId: 'configId1', authority: 'some-authority1' },
|
||||
allConfigs,
|
||||
undefined,
|
||||
],
|
||||
[
|
||||
{ configId: 'configId2', authority: 'some-authority2' },
|
||||
allConfigs,
|
||||
undefined,
|
||||
],
|
||||
]);
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuthMultiple(allConfigs)
|
||||
);
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(spy).toBeCalledWith([
|
||||
[
|
||||
{ configId: 'configId1', authority: 'some-authority1' },
|
||||
allConfigs,
|
||||
undefined,
|
||||
],
|
||||
[
|
||||
{ configId: 'configId2', authority: 'some-authority2' },
|
||||
allConfigs,
|
||||
undefined,
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('runs through all configs if no parameter is passed and has no state in url', async () => {
|
||||
@ -847,19 +886,21 @@ expect(spy).toBeCalledWith([
|
||||
|
||||
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
|
||||
|
||||
const result = await lastValueFrom(checkAuthService.checkAuthMultiple(allConfigs));
|
||||
expect(Array.isArray(result)).toBe(true);;
|
||||
expect(spy).toHaveBeenCalledTimes(2);;
|
||||
expect(vi.mocked(spy).mock.calls[0]).toEqual([
|
||||
{ configId: 'configId1', authority: 'some-authority1' },
|
||||
allConfigs,
|
||||
undefined,
|
||||
]);;
|
||||
expect(vi.mocked(spy).mock.calls[1]).toEqual([
|
||||
{ configId: 'configId2', authority: 'some-authority2' },
|
||||
allConfigs,
|
||||
undefined,
|
||||
]);
|
||||
const result = await lastValueFrom(
|
||||
checkAuthService.checkAuthMultiple(allConfigs)
|
||||
);
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
expect(vi.mocked(spy).mock.calls[0]).toEqual([
|
||||
{ configId: 'configId1', authority: 'some-authority1' },
|
||||
allConfigs,
|
||||
undefined,
|
||||
]);
|
||||
expect(vi.mocked(spy).mock.calls[1]).toEqual([
|
||||
{ configId: 'configId2', authority: 'some-authority2' },
|
||||
allConfigs,
|
||||
undefined,
|
||||
]);
|
||||
});
|
||||
|
||||
it('throws error if url has state param but no config could be found', async () => {
|
||||
@ -870,13 +911,13 @@ expect(vi.mocked(spy).mock.calls[1]).toEqual([
|
||||
|
||||
const allConfigs: OpenIdConfiguration[] = [];
|
||||
|
||||
checkAuthService.checkAuthMultiple(allConfigs).subscribe({
|
||||
error: (error) => {
|
||||
expect(error.message).toEqual(
|
||||
'could not find matching config for state the-state-param'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(checkAuthService.checkAuthMultiple(allConfigs));
|
||||
} catch (error: any) {
|
||||
expect(error.message).toEqual(
|
||||
'could not find matching config for state the-state-param'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ export class CheckAuthService {
|
||||
const stateParamFromUrl =
|
||||
this.currentUrlService.getStateParamFromCurrentUrl(url);
|
||||
|
||||
return Boolean(stateParamFromUrl)
|
||||
return stateParamFromUrl
|
||||
? this.getConfigurationWithUrlState([configuration], stateParamFromUrl)
|
||||
: configuration;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { PASSED_CONFIG } from './auth-config';
|
||||
import { AuthModule } from './auth.module';
|
||||
import { ConfigurationService } from './config/config.service';
|
||||
|
@ -4,7 +4,7 @@ import {
|
||||
type ActivatedRouteSnapshot,
|
||||
type RouterStateSnapshot,
|
||||
} from 'oidc-client-rx';
|
||||
import { of } from 'rxjs';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { CheckAuthService } from '../auth-state/check-auth.service';
|
||||
|
@ -16,9 +16,6 @@ describe('AutoLoginService ', () => {
|
||||
imports: [RouterTestingModule],
|
||||
providers: [AutoLoginService, mockProvider(StoragePersistenceService)],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
router = TestBed.inject(Router);
|
||||
autoLoginService = TestBed.inject(AutoLoginService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Router } from '@angular/router';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
|
||||
const STORAGE_KEY = 'redirect';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TestBed, mockRouterProvider } from '@/testing';
|
||||
import { AbstractRouter } from 'oidc-client-rx';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
@ -85,13 +85,18 @@ describe('CodeFlowCallbackService ', () => {
|
||||
triggerAuthorizationResultEvent: true,
|
||||
};
|
||||
|
||||
await lastValueFrom(codeFlowCallbackService
|
||||
.authenticatedCallbackWithCode('some-url2', config, [config]));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-url2', config, [
|
||||
config,
|
||||
]);;
|
||||
expect(routerSpy).not.toHaveBeenCalled();;
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
codeFlowCallbackService.authenticatedCallbackWithCode(
|
||||
'some-url2',
|
||||
config,
|
||||
[config]
|
||||
)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-url2', config, [
|
||||
config,
|
||||
]);
|
||||
expect(routerSpy).not.toHaveBeenCalled();
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls router and resetCodeFlowInProgress if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => {
|
||||
@ -120,13 +125,18 @@ expect(flowsDataSpy).toHaveBeenCalled();
|
||||
postLoginRoute: 'postLoginRoute',
|
||||
};
|
||||
|
||||
await lastValueFrom(codeFlowCallbackService
|
||||
.authenticatedCallbackWithCode('some-url3', config, [config]));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-url3', config, [
|
||||
config,
|
||||
]);;
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');;
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
codeFlowCallbackService.authenticatedCallbackWithCode(
|
||||
'some-url3',
|
||||
config,
|
||||
[config]
|
||||
)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-url3', config, [
|
||||
config,
|
||||
]);
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('resetSilentRenewRunning, resetCodeFlowInProgress and stopPeriodicallTokenCheck in case of error', async () => {
|
||||
@ -152,16 +162,20 @@ expect(flowsDataSpy).toHaveBeenCalled();
|
||||
postLoginRoute: 'postLoginRoute',
|
||||
};
|
||||
|
||||
codeFlowCallbackService
|
||||
.authenticatedCallbackWithCode('some-url4', config, [config])
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(resetCodeFlowInProgressSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
codeFlowCallbackService.authenticatedCallbackWithCode(
|
||||
'some-url4',
|
||||
config,
|
||||
[config]
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(resetCodeFlowInProgressSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it(`navigates to unauthorizedRoute in case of error and in case of error and
|
||||
@ -186,18 +200,20 @@ expect(flowsDataSpy).toHaveBeenCalled();
|
||||
unauthorizedRoute: 'unauthorizedRoute',
|
||||
};
|
||||
|
||||
codeFlowCallbackService
|
||||
.authenticatedCallbackWithCode('some-url5', config, [config])
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'unauthorizedRoute'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
codeFlowCallbackService.authenticatedCallbackWithCode(
|
||||
'some-url5',
|
||||
config,
|
||||
[config]
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('unauthorizedRoute');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TestBed, mockRouterProvider } from '@/testing';
|
||||
import { AbstractRouter } from 'oidc-client-rx';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
@ -81,14 +81,19 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
triggerAuthorizationResultEvent: true,
|
||||
};
|
||||
|
||||
await lastValueFrom(implicitFlowCallbackService
|
||||
.authenticatedImplicitFlowCallback(config, [config], 'some-hash'));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
);;
|
||||
expect(routerSpy).not.toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
implicitFlowCallbackService.authenticatedImplicitFlowCallback(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
);
|
||||
expect(routerSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls router if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => {
|
||||
@ -113,14 +118,19 @@ expect(routerSpy).not.toHaveBeenCalled();
|
||||
postLoginRoute: 'postLoginRoute',
|
||||
};
|
||||
|
||||
await lastValueFrom(implicitFlowCallbackService
|
||||
.authenticatedImplicitFlowCallback(config, [config], 'some-hash'));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
);;
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
|
||||
await lastValueFrom(
|
||||
implicitFlowCallbackService.authenticatedImplicitFlowCallback(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
);
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
|
||||
});
|
||||
|
||||
it('resetSilentRenewRunning and stopPeriodicallyTokenCheck in case of error', async () => {
|
||||
@ -141,15 +151,19 @@ expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
|
||||
postLoginRoute: 'postLoginRoute',
|
||||
};
|
||||
|
||||
implicitFlowCallbackService
|
||||
.authenticatedImplicitFlowCallback(config, [config], 'some-hash')
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallyTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
implicitFlowCallbackService.authenticatedImplicitFlowCallback(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallyTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it(`navigates to unauthorizedRoute in case of error and in case of error and
|
||||
@ -173,18 +187,20 @@ expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
|
||||
unauthorizedRoute: 'unauthorizedRoute',
|
||||
};
|
||||
|
||||
implicitFlowCallbackService
|
||||
.authenticatedImplicitFlowCallback(config, [config], 'some-hash')
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'unauthorizedRoute'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
implicitFlowCallbackService.authenticatedImplicitFlowCallback(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('unauthorizedRoute');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { TestBed, fakeAsync, tick } from '@/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { IntervalService } from './interval.service';
|
||||
@ -19,9 +19,6 @@ describe('IntervalService', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
intervalService = TestBed.inject(IntervalService);
|
||||
});
|
||||
|
||||
@ -60,15 +57,15 @@ describe('IntervalService', () => {
|
||||
describe('startPeriodicTokenCheck', () => {
|
||||
it('starts check after correct milliseconds', async () => {
|
||||
const periodicCheck = intervalService.startPeriodicTokenCheck(0.5);
|
||||
const spy = jasmine.createSpy();
|
||||
const spy = vi.fn();
|
||||
const sub = periodicCheck.subscribe(() => {
|
||||
spy();
|
||||
});
|
||||
|
||||
tick(500);
|
||||
await vi.advanceTimersByTimeAsync(500);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
|
||||
tick(500);
|
||||
await vi.advanceTimersByTimeAsync(500);
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
|
||||
sub.unsubscribe();
|
||||
|
@ -62,16 +62,17 @@ describe('RefreshSessionRefreshTokenService', () => {
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
|
||||
refreshSessionRefreshTokenService
|
||||
.refreshSessionWithRefreshTokens({ configId: 'configId1' }, [
|
||||
{ configId: 'configId1' },
|
||||
])
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
refreshSessionRefreshTokenService.refreshSessionWithRefreshTokens(
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('finalize with stopPeriodicTokenCheck in case of error', async () => {
|
||||
@ -83,15 +84,16 @@ describe('RefreshSessionRefreshTokenService', () => {
|
||||
'stopPeriodicTokenCheck'
|
||||
);
|
||||
|
||||
refreshSessionRefreshTokenService
|
||||
.refreshSessionWithRefreshTokens({ configId: 'configId1' }, [
|
||||
{ configId: 'configId1' },
|
||||
])
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
refreshSessionRefreshTokenService.refreshSessionWithRefreshTokens(
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
expect(stopPeriodicallyTokenCheckSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TestBed, spyOnProperty } from '@/testing';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { EmptyError, lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { delay } from 'rxjs/operators';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
@ -216,18 +216,22 @@ describe('RefreshSessionService ', () => {
|
||||
},
|
||||
];
|
||||
|
||||
refreshSessionService
|
||||
.userForceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect.fail('It should not return any error.');
|
||||
},
|
||||
complete: () => {
|
||||
expect(
|
||||
flowsDataService.resetSilentRenewRunning
|
||||
).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
refreshSessionService.userForceRefreshSession(
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
if (err instanceof EmptyError) {
|
||||
expect(
|
||||
flowsDataService.resetSilentRenewRunning
|
||||
).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
|
||||
} else {
|
||||
expect.fail('It should not return any error.');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -448,18 +452,16 @@ describe('RefreshSessionService ', () => {
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
|
||||
refreshSessionService
|
||||
.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
expect.fail('It should not return any result.');
|
||||
},
|
||||
error: (error) => {
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
expect(error.message).toEqual(`Error: ${expectedErrorMessage}`);
|
||||
expect(resetSilentRenewRunningSpy).not.toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
refreshSessionService.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect.fail('It should not return any result.');
|
||||
} catch (error: any) {
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
expect(error.message).toEqual(`Error: ${expectedErrorMessage}`);
|
||||
expect(resetSilentRenewRunningSpy).not.toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
|
||||
describe('NOT isCurrentFlowCodeFlowWithRefreshTokens', () => {
|
||||
|
@ -39,9 +39,6 @@ describe('AuthWellKnownDataService', () => {
|
||||
mockProvider(LoggerService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(AuthWellKnownDataService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
dataService = TestBed.inject(DataService);
|
||||
@ -73,7 +70,7 @@ describe('AuthWellKnownDataService', () => {
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'get')
|
||||
.mockReturnValue(of(null));
|
||||
const urlWithSuffix = `myUrl/.well-known/openid-configuration`;
|
||||
const urlWithSuffix = 'myUrl/.well-known/openid-configuration';
|
||||
|
||||
await lastValueFrom(
|
||||
(service as any).getWellKnownDocument(urlWithSuffix, {
|
||||
@ -89,7 +86,8 @@ describe('AuthWellKnownDataService', () => {
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'get')
|
||||
.mockReturnValue(of(null));
|
||||
const urlWithSuffix = `myUrl/.well-known/openid-configuration/and/some/more/stuff`;
|
||||
const urlWithSuffix =
|
||||
'myUrl/.well-known/openid-configuration/and/some/more/stuff';
|
||||
|
||||
await lastValueFrom(
|
||||
(service as any).getWellKnownDocument(urlWithSuffix, {
|
||||
@ -105,7 +103,7 @@ describe('AuthWellKnownDataService', () => {
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'get')
|
||||
.mockReturnValue(of(null));
|
||||
const urlWithoutSuffix = `myUrl`;
|
||||
const urlWithoutSuffix = 'myUrl';
|
||||
const urlWithSuffix = `${urlWithoutSuffix}/.well-known/test-openid-configuration`;
|
||||
|
||||
await lastValueFrom(
|
||||
@ -128,14 +126,13 @@ describe('AuthWellKnownDataService', () => {
|
||||
)
|
||||
);
|
||||
|
||||
(service as any)
|
||||
.getWellKnownDocument('anyurl', { configId: 'configId1' })
|
||||
.subscribe({
|
||||
next: (res: unknown) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_WELL_KNOWN_DOCUMENT);
|
||||
},
|
||||
});
|
||||
const res: unknown = await lastValueFrom(
|
||||
(service as any).getWellKnownDocument('anyurl', {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_WELL_KNOWN_DOCUMENT);
|
||||
});
|
||||
|
||||
it('should retry twice', async () => {
|
||||
@ -147,14 +144,13 @@ describe('AuthWellKnownDataService', () => {
|
||||
)
|
||||
);
|
||||
|
||||
(service as any)
|
||||
.getWellKnownDocument('anyurl', { configId: 'configId1' })
|
||||
.subscribe({
|
||||
next: (res: any) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_WELL_KNOWN_DOCUMENT);
|
||||
},
|
||||
});
|
||||
const res: any = await lastValueFrom(
|
||||
(service as any).getWellKnownDocument('anyurl', {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_WELL_KNOWN_DOCUMENT);
|
||||
});
|
||||
|
||||
it('should fail after three tries', async () => {
|
||||
@ -167,11 +163,13 @@ describe('AuthWellKnownDataService', () => {
|
||||
)
|
||||
);
|
||||
|
||||
(service as any).getWellKnownDocument('anyurl', 'configId').subscribe({
|
||||
error: (err: unknown) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
(service as any).getWellKnownDocument('anyurl', 'configId')
|
||||
);
|
||||
} catch (err: unknown) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -181,7 +179,7 @@ describe('AuthWellKnownDataService', () => {
|
||||
of({ jwks_uri: 'jwks_uri' })
|
||||
);
|
||||
|
||||
const spy = vi.spyOn(service as any, 'getWellKnownDocument')();
|
||||
const spy = vi.spyOn(service as any, 'getWellKnownDocument');
|
||||
|
||||
const result = await lastValueFrom(
|
||||
service.getWellKnownEndPointsForConfig({
|
||||
@ -201,15 +199,15 @@ describe('AuthWellKnownDataService', () => {
|
||||
authWellknownEndpointUrl: undefined,
|
||||
};
|
||||
|
||||
service.getWellKnownEndPointsForConfig(config).subscribe({
|
||||
error: (error) => {
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
'no authWellknownEndpoint given!'
|
||||
);
|
||||
expect(error.message).toEqual('no authWellknownEndpoint given!');
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.getWellKnownEndPointsForConfig(config));
|
||||
} catch (error: any) {
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
'no authWellknownEndpoint given!'
|
||||
);
|
||||
expect(error.message).toEqual('no authWellknownEndpoint given!');
|
||||
}
|
||||
});
|
||||
|
||||
it('should merge the mapped endpoints with the provided endpoints', async () => {
|
||||
@ -233,7 +231,7 @@ describe('AuthWellKnownDataService', () => {
|
||||
},
|
||||
})
|
||||
);
|
||||
expect(result).toEqual(jasmine.objectContaining(expected));
|
||||
expect(result).toEqual(expect.objectContaining(expected));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { map, retry } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { OpenIdConfiguration } from '../openid-configuration';
|
||||
import { AuthWellKnownEndpoints } from './auth-well-known-endpoints';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
import type { AuthWellKnownEndpoints } from './auth-well-known-endpoints';
|
||||
|
||||
const WELL_KNOWN_SUFFIX = `/.well-known/openid-configuration`;
|
||||
const WELL_KNOWN_SUFFIX = '/.well-known/openid-configuration';
|
||||
|
||||
@Injectable()
|
||||
export class AuthWellKnownDataService {
|
||||
|
@ -35,15 +35,15 @@ describe('AuthWellKnownService', () => {
|
||||
|
||||
describe('getAuthWellKnownEndPoints', () => {
|
||||
it('getAuthWellKnownEndPoints throws an error if not config provided', async () => {
|
||||
service.queryAndStoreAuthWellKnownEndPoints(null).subscribe({
|
||||
error: (error) => {
|
||||
expect(error).toEqual(
|
||||
new Error(
|
||||
'Please provide a configuration before setting up the module'
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.queryAndStoreAuthWellKnownEndPoints(null));
|
||||
} catch (error) {
|
||||
expect(error).toEqual(
|
||||
new Error(
|
||||
'Please provide a configuration before setting up the module'
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('getAuthWellKnownEndPoints calls always dataservice', async () => {
|
||||
@ -91,18 +91,18 @@ describe('AuthWellKnownService', () => {
|
||||
);
|
||||
const publicEventsServiceSpy = vi.spyOn(publicEventsService, 'fireEvent');
|
||||
|
||||
service
|
||||
.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(publicEventsServiceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(publicEventsServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
EventTypes.ConfigLoadingFailed,
|
||||
null
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(publicEventsServiceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(publicEventsServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
EventTypes.ConfigLoadingFailed,
|
||||
null
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, tap } from 'rxjs/operators';
|
||||
import { EventTypes } from '../../public-events/event-types';
|
||||
import { PublicEventsService } from '../../public-events/public-events.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { OpenIdConfiguration } from '../openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
import { AuthWellKnownDataService } from './auth-well-known-data.service';
|
||||
import { AuthWellKnownEndpoints } from './auth-well-known-endpoints';
|
||||
import type { AuthWellKnownEndpoints } from './auth-well-known-endpoints';
|
||||
|
||||
@Injectable()
|
||||
export class AuthWellKnownService {
|
||||
|
@ -276,7 +276,9 @@ describe('Configuration Service', () => {
|
||||
false
|
||||
);
|
||||
|
||||
await lastValueFrom(configService.getOpenIDConfigurations());
|
||||
const { allConfigs, currentConfig } = await lastValueFrom(
|
||||
configService.getOpenIDConfigurations()
|
||||
);
|
||||
expect(allConfigs).toEqual([]);
|
||||
expect(currentConfig).toBeNull();
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { LogLevel } from '../logging/log-level';
|
||||
import { OpenIdConfiguration } from './openid-configuration';
|
||||
import type { OpenIdConfiguration } from './openid-configuration';
|
||||
|
||||
export const DEFAULT_CONFIG: OpenIdConfiguration = {
|
||||
authority: 'https://please_set',
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { waitForAsync } from '@/testing';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
import { StsConfigHttpLoader, StsConfigStaticLoader } from './config-loader';
|
||||
@ -46,8 +45,8 @@ describe('ConfigLoader', () => {
|
||||
|
||||
const result = await lastValueFrom(result$);
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result[0].configId).toBe('configId1');
|
||||
expect(result[1].configId).toBe('configId2');
|
||||
expect(result[0]!.configId).toBe('configId1');
|
||||
expect(result[1]!.configId).toBe('configId2');
|
||||
});
|
||||
|
||||
it('returns an array if an observable with a config array is passed', async () => {
|
||||
@ -61,8 +60,8 @@ describe('ConfigLoader', () => {
|
||||
|
||||
const result = await lastValueFrom(result$);
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result[0].configId).toBe('configId1');
|
||||
expect(result[1].configId).toBe('configId2');
|
||||
expect(result[0]!.configId).toBe('configId1');
|
||||
expect(result[1]!.configId).toBe('configId2');
|
||||
});
|
||||
|
||||
it('returns an array if only one config is passed', async () => {
|
||||
@ -74,7 +73,7 @@ describe('ConfigLoader', () => {
|
||||
|
||||
const result = await lastValueFrom(result$);
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result[0].configId).toBe('configId1');
|
||||
expect(result[0]!.configId).toBe('configId1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { OpenIdConfiguration } from '../openid-configuration';
|
||||
import { Level, RuleValidationResult } from './rule';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
import type { Level, RuleValidationResult } from './rule';
|
||||
import { allMultipleConfigRules, allRules } from './rules';
|
||||
|
||||
@Injectable()
|
||||
@ -35,14 +35,14 @@ export class ConfigValidationService {
|
||||
|
||||
let overallErrorCount = 0;
|
||||
|
||||
passedConfigs.forEach((passedConfig) => {
|
||||
for (const passedConfig of passedConfigs) {
|
||||
const errorCount = this.processValidationResultsAndGetErrorCount(
|
||||
allValidationResults,
|
||||
passedConfig
|
||||
);
|
||||
|
||||
overallErrorCount += errorCount;
|
||||
});
|
||||
}
|
||||
|
||||
return overallErrorCount === 0;
|
||||
}
|
||||
@ -75,12 +75,12 @@ export class ConfigValidationService {
|
||||
const allErrorMessages = this.getAllMessagesOfType('error', allMessages);
|
||||
const allWarnings = this.getAllMessagesOfType('warning', allMessages);
|
||||
|
||||
allErrorMessages.forEach((message) =>
|
||||
this.loggerService.logError(config, message)
|
||||
);
|
||||
allWarnings.forEach((message) =>
|
||||
this.loggerService.logWarning(config, message)
|
||||
);
|
||||
for (const message of allErrorMessages) {
|
||||
this.loggerService.logError(config, message);
|
||||
}
|
||||
for (const message of allWarnings) {
|
||||
this.loggerService.logWarning(config, message);
|
||||
}
|
||||
|
||||
return allErrorMessages.length;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { OpenIdConfiguration } from '../openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
|
||||
export interface Rule {
|
||||
validate(passedConfig: OpenIdConfiguration): RuleValidationResult;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, RuleValidationResult } from '../rule';
|
||||
import type { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, type RuleValidationResult } from '../rule';
|
||||
|
||||
export const ensureAuthority = (
|
||||
passedConfig: OpenIdConfiguration
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, RuleValidationResult } from '../rule';
|
||||
import type { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, type RuleValidationResult } from '../rule';
|
||||
|
||||
export const ensureClientId = (
|
||||
passedConfig: OpenIdConfiguration
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, RuleValidationResult } from '../rule';
|
||||
import type { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, type RuleValidationResult } from '../rule';
|
||||
|
||||
const createIdentifierToCheck = (passedConfig: OpenIdConfiguration): string => {
|
||||
if (!passedConfig) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, RuleValidationResult } from '../rule';
|
||||
import type { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, type RuleValidationResult } from '../rule';
|
||||
|
||||
export const ensureRedirectRule = (
|
||||
passedConfig: OpenIdConfiguration
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, RuleValidationResult } from '../rule';
|
||||
import type { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, type RuleValidationResult } from '../rule';
|
||||
|
||||
export const ensureSilentRenewUrlWhenNoRefreshTokenUsed = (
|
||||
passedConfig: OpenIdConfiguration
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, RuleValidationResult } from '../rule';
|
||||
import type { OpenIdConfiguration } from '../../openid-configuration';
|
||||
import { POSITIVE_VALIDATION_RESULT, type RuleValidationResult } from '../rule';
|
||||
|
||||
export const useOfflineScopeWithSilentRenew = (
|
||||
passedConfig: OpenIdConfiguration
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { CryptoService } from '../utils/crypto/crypto.service';
|
||||
import {
|
||||
JwkExtractor,
|
||||
@ -94,9 +93,6 @@ describe('JwkExtractor', () => {
|
||||
imports: [],
|
||||
providers: [JwkExtractor, CryptoService],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(JwkExtractor);
|
||||
});
|
||||
|
||||
|
@ -7,20 +7,20 @@ export class JwkExtractor {
|
||||
spec?: { kid?: string; use?: string; kty?: string },
|
||||
throwOnEmpty = true
|
||||
): JsonWebKey[] {
|
||||
if (0 === keys.length) {
|
||||
if (keys.length === 0) {
|
||||
throw JwkExtractorInvalidArgumentError;
|
||||
}
|
||||
|
||||
const foundKeys = keys
|
||||
.filter((k) => (spec?.kid ? (k as any)['kid'] === spec.kid : true))
|
||||
.filter((k) => (spec?.use ? k['use'] === spec.use : true))
|
||||
.filter((k) => (spec?.kty ? k['kty'] === spec.kty : true));
|
||||
.filter((k) => (spec?.kid ? (k as any).kid === spec.kid : true))
|
||||
.filter((k) => (spec?.use ? k.use === spec.use : true))
|
||||
.filter((k) => (spec?.kty ? k.kty === spec.kty : true));
|
||||
|
||||
if (foundKeys.length === 0 && throwOnEmpty) {
|
||||
throw JwkExtractorNoMatchingKeysError;
|
||||
}
|
||||
|
||||
if (foundKeys.length > 1 && (null === spec || undefined === spec)) {
|
||||
if (foundKeys.length > 1 && (spec === null || undefined === spec)) {
|
||||
throw JwkExtractorSeveralMatchingKeysError;
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ export class JwkExtractor {
|
||||
}
|
||||
|
||||
function buildErrorName(name: string): string {
|
||||
return JwkExtractor.name + ': ' + name;
|
||||
return `${JwkExtractor.name}: ${name}`;
|
||||
}
|
||||
|
||||
export const JwkExtractorInvalidArgumentError = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { JwtKeys } from '../validation/jwtkeys';
|
||||
import { StateValidationResult } from '../validation/state-validation-result';
|
||||
import type { JwtKeys } from '../validation/jwtkeys';
|
||||
import type { StateValidationResult } from '../validation/state-validation-result';
|
||||
|
||||
export interface CallbackContext {
|
||||
code: string;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpErrorResponse, HttpHeaders } from '@ngify/http';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@ -32,9 +32,6 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
mockProvider(DataService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(CodeFlowCallbackHandlerService);
|
||||
dataService = TestBed.inject(DataService);
|
||||
urlService = TestBed.inject(UrlService);
|
||||
@ -58,13 +55,13 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
() => ''
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('throws error if no code is given', async () => {
|
||||
@ -72,15 +69,19 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
.spyOn(urlService, 'getUrlParameter')
|
||||
.mockReturnValue('params');
|
||||
|
||||
getUrlParameterSpy.withArgs('test-url', 'code').mockReturnValue('');
|
||||
mockImplementationWhenArgsEqual(
|
||||
getUrlParameterSpy,
|
||||
['test-url', 'code'],
|
||||
() => ''
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('returns callbackContext if all params are good', async () => {
|
||||
@ -98,9 +99,10 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
existingIdToken: null,
|
||||
} as CallbackContext;
|
||||
|
||||
const callbackContext = await lastValueFrom(service
|
||||
.codeFlowCallback('test-url', { configId: 'configId1' }));
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
const callbackContext = await lastValueFrom(
|
||||
service.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
);
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
});
|
||||
|
||||
@ -119,13 +121,15 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(false);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('throws error if authWellknownEndpoints is null is given', async () => {
|
||||
@ -139,13 +143,15 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
() => null
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('throws error if tokenendpoint is null is given', async () => {
|
||||
@ -159,13 +165,15 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
() => ({ tokenEndpoint: null })
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('calls dataService if all params are good', async () => {
|
||||
@ -182,14 +190,17 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(true);
|
||||
|
||||
await lastValueFrom(service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' }));
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
});
|
||||
|
||||
it('calls url service with custom token params', async () => {
|
||||
@ -215,12 +226,13 @@ expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
|
||||
|
||||
await lastValueFrom(service
|
||||
.codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config));
|
||||
expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, {
|
||||
foo: 'bar',
|
||||
});;
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config)
|
||||
);
|
||||
expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, {
|
||||
foo: 'bar',
|
||||
});
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('calls dataService with correct headers if all params are good', async () => {
|
||||
@ -241,13 +253,14 @@ expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(true);
|
||||
|
||||
await lastValueFrom(service
|
||||
.codeFlowCodeRequest({} as CallbackContext, config));
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();;
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config)
|
||||
);
|
||||
const httpHeaders = postSpy.mock.calls.at(-1)?.[3] as HttpHeaders;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
|
||||
it('returns error in case of http error', async () => {
|
||||
@ -266,11 +279,13 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and succeeds', async () => {
|
||||
@ -297,16 +312,15 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(true);
|
||||
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
error: (err) => {
|
||||
// fails if there should be a result
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const res = await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config)
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and fails because of http error afterwards', async () => {
|
||||
@ -333,16 +347,15 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'validateStateFromHashCallback'
|
||||
).mockReturnValue(true);
|
||||
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
|
||||
next: (res) => {
|
||||
// fails if there should be a result
|
||||
expect(res).toBeFalsy();
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
});
|
||||
try {
|
||||
const res = await lastValueFrom(
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config)
|
||||
);
|
||||
expect(res).toBeFalsy();
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError, timer } from 'rxjs';
|
||||
import { type Observable, of, throwError, timer } from 'rxjs';
|
||||
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { TokenValidationService } from '../../validation/token-validation.service';
|
||||
import { AuthResult, CallbackContext } from '../callback-context';
|
||||
import type { AuthResult, CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { isNetworkError } from './error-helper';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@ -83,17 +83,18 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);;
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('writes refresh_token into the storage without reuse (refresh token rotation)', async () => {
|
||||
@ -120,17 +121,18 @@ expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
|
||||
await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);;
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('writes refresh_token into the storage with reuse (without refresh token rotation)', async () => {
|
||||
@ -157,18 +159,19 @@ expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['reusable_refresh_token', 'dummy_refresh_token', allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);;
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3);
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['reusable_refresh_token', 'dummy_refresh_token', allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it('resetBrowserHistory if historyCleanup is turned on and is not in a renewProcess', async () => {
|
||||
@ -191,13 +194,14 @@ expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3);
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(windowSpy).toHaveBeenCalledTimes(1);
|
||||
)
|
||||
);
|
||||
expect(windowSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('returns callbackContext with jwtkeys filled if everything works fine', async () => {
|
||||
@ -219,17 +223,18 @@ expect(windowSpy).toHaveBeenCalledTimes(1);
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [{ kty: 'henlo' } as JwtKey] } as JwtKeys)
|
||||
);
|
||||
const result = await lastValueFrom(service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
const result = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(result).toEqual({
|
||||
isRenewProcess: false,
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
jwtKeys: { keys: [{ kty: 'henlo' }] },
|
||||
} as CallbackContext);
|
||||
)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
isRenewProcess: false,
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
jwtKeys: { keys: [{ kty: 'henlo' }] },
|
||||
} as CallbackContext);
|
||||
});
|
||||
|
||||
it('returns error if no jwtKeys have been in the call --> keys are null', async () => {
|
||||
@ -251,19 +256,19 @@ expect(result).toEqual({
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({} as JwtKeys)
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve signing key with error: Error: Failed to retrieve signing key'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve signing key with error: Error: Failed to retrieve signing key'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns error if no jwtKeys have been in the call --> keys throw an error', async () => {
|
||||
@ -284,19 +289,19 @@ expect(result).toEqual({
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve signing key with error: Error: Error: error'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve signing key with error: Error: Error: error'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns error if callbackContext.authresult has an error property filled', async () => {
|
||||
@ -310,19 +315,19 @@ expect(result).toEqual({
|
||||
},
|
||||
];
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual(
|
||||
'AuthCallback AuthResult came with error: someError'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err.message).toEqual(
|
||||
'AuthCallback AuthResult came with error: someError'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('calls resetAuthorizationData, resets nonce and authStateService in case of an error', async () => {
|
||||
@ -347,25 +352,23 @@ expect(result).toEqual({
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.SecureTokenServerError,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
},
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.SecureTokenServerError,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('calls authStateService.updateAndPublishAuthState with login required if the error is `login_required`', async () => {
|
||||
@ -390,25 +393,23 @@ expect(result).toEqual({
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
},
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('should store jwtKeys', async () => {
|
||||
@ -434,26 +435,23 @@ expect(result).toEqual({
|
||||
of(DUMMY_JWT_KEYS)
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', DUMMY_JWT_KEYS, allConfigs[0]],
|
||||
]);
|
||||
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const callbackContext: CallbackContext = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', DUMMY_JWT_KEYS, allConfigs[0]],
|
||||
]);
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
});
|
||||
|
||||
it('should not store jwtKeys on error', async () => {
|
||||
@ -480,29 +478,23 @@ expect(result).toEqual({
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(callbackContext).toBeFalsy();
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
|
||||
// storagePersistenceService.write() should not have been called with jwtKeys
|
||||
expect(
|
||||
storagePersistenceServiceSpy
|
||||
).toHaveBeenCalledExactlyOnceWith(
|
||||
'authnResult',
|
||||
authResult,
|
||||
allConfigs[0]
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
const callbackContext: CallbackContext = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(callbackContext).toBeFalsy();
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'authnResult',
|
||||
authResult,
|
||||
allConfigs[0]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should fallback to stored jwtKeys on error', async () => {
|
||||
@ -530,23 +522,22 @@ expect(result).toEqual({
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(
|
||||
storagePersistenceServiceSpy
|
||||
).toHaveBeenCalledExactlyOnceWith('jwtKeys', allConfigs[0]);
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const callbackContext: CallbackContext = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'jwtKeys',
|
||||
allConfigs[0]
|
||||
);
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw error if no jwtKeys are stored', async () => {
|
||||
@ -568,20 +559,18 @@ expect(result).toEqual({
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(callbackContext).toBeFalsy();
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const callbackContext: CallbackContext = await lastValueFrom(
|
||||
service.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(callbackContext).toBeFalsy();
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -98,10 +98,10 @@ export class HistoryJwtKeysCallbackHandlerService {
|
||||
// fallback: try to load jwtKeys from storage
|
||||
const storedJwtKeys = this.readSigningKeys(config);
|
||||
|
||||
if (!!storedJwtKeys) {
|
||||
if (storedJwtKeys) {
|
||||
this.loggerService.logWarning(
|
||||
config,
|
||||
`Failed to retrieve signing keys, fallback to stored keys`
|
||||
'Failed to retrieve signing keys, fallback to stored keys'
|
||||
);
|
||||
|
||||
return of(storedJwtKeys);
|
||||
@ -116,7 +116,7 @@ export class HistoryJwtKeysCallbackHandlerService {
|
||||
return of(callbackContext);
|
||||
}
|
||||
|
||||
const errorMessage = `Failed to retrieve signing key`;
|
||||
const errorMessage = 'Failed to retrieve signing key';
|
||||
|
||||
this.loggerService.logWarning(config, errorMessage);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@ -57,9 +58,10 @@ describe('ImplicitFlowCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
await lastValueFrom(service
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash'));
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
service.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
|
||||
);
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does NOT calls "resetAuthorizationData" if silent renew is running', async () => {
|
||||
@ -74,9 +76,10 @@ expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
},
|
||||
];
|
||||
|
||||
await lastValueFrom(service
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash'));
|
||||
expect(resetAuthorizationDataSpy).not.toHaveBeenCalled();
|
||||
await lastValueFrom(
|
||||
service.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
|
||||
);
|
||||
expect(resetAuthorizationDataSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns callbackContext if all params are good', async () => {
|
||||
@ -99,9 +102,10 @@ expect(resetAuthorizationDataSpy).not.toHaveBeenCalled();
|
||||
},
|
||||
];
|
||||
|
||||
const callbackContext = await lastValueFrom(service
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'anyHash'));
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
const callbackContext = await lastValueFrom(
|
||||
service.implicitFlowCallback(allConfigs[0]!, allConfigs, 'anyHash')
|
||||
);
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
|
||||
it('uses window location hash if no hash is passed', async () => {
|
||||
@ -124,9 +128,10 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
},
|
||||
];
|
||||
|
||||
const callbackContext = await lastValueFrom(service
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs));
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
const callbackContext = await lastValueFrom(
|
||||
service.implicitFlowCallback(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@ -21,9 +22,6 @@ describe('RefreshSessionCallbackHandlerService', () => {
|
||||
mockProvider(FlowsDataService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(RefreshSessionCallbackHandlerService);
|
||||
flowsDataService = TestBed.inject(FlowsDataService);
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@ -56,9 +54,10 @@ describe('RefreshSessionCallbackHandlerService', () => {
|
||||
existingIdToken: 'henlo-legger',
|
||||
} as CallbackContext;
|
||||
|
||||
const callbackContext = await lastValueFrom(service
|
||||
.refreshSessionWithRefreshTokens({ configId: 'configId1' }));
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
const callbackContext = await lastValueFrom(
|
||||
service.refreshSessionWithRefreshTokens({ configId: 'configId1' })
|
||||
);
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
|
||||
it('throws error if no refresh token is given', async () => {
|
||||
@ -69,13 +68,13 @@ expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
vi.spyOn(authStateService, 'getRefreshToken').mockReturnValue('');
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('henlo-legger');
|
||||
|
||||
service
|
||||
.refreshSessionWithRefreshTokens({ configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.refreshSessionWithRefreshTokens({ configId: 'configId1' })
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { TokenValidationService } from '../../validation/token-validation.service';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
|
||||
@Injectable()
|
||||
@ -24,7 +24,7 @@ export class RefreshSessionCallbackHandlerService {
|
||||
|
||||
this.loggerService.logDebug(
|
||||
config,
|
||||
'RefreshSession created. Adding myautostate: ' + stateData
|
||||
`RefreshSession created. Adding myautostate: ${stateData}`
|
||||
);
|
||||
const refreshToken = this.authStateService.getRefreshToken(config);
|
||||
const idToken = this.authStateService.getIdToken(config);
|
||||
@ -53,12 +53,11 @@ export class RefreshSessionCallbackHandlerService {
|
||||
);
|
||||
|
||||
return of(callbackContext);
|
||||
} else {
|
||||
const errorMessage = 'no refresh token found, please login';
|
||||
|
||||
this.loggerService.logError(config, errorMessage);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}
|
||||
const errorMessage = 'no refresh token found, please login';
|
||||
|
||||
this.loggerService.logError(config, errorMessage);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpErrorResponse, HttpHeaders } from '@ngify/http';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@ -26,9 +26,6 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
mockProvider(StoragePersistenceService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(RefreshTokenCallbackHandlerService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
dataService = TestBed.inject(DataService);
|
||||
@ -48,13 +45,13 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
});
|
||||
|
||||
it('throws error if no tokenEndpoint is given', async () => {
|
||||
(service as any)
|
||||
.refreshTokensRequestTokens({} as CallbackContext)
|
||||
.subscribe({
|
||||
error: (err: unknown) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
(service as any).refreshTokensRequestTokens({} as CallbackContext)
|
||||
);
|
||||
} catch (err: unknown) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('calls data service if all params are good', async () => {
|
||||
@ -66,21 +63,22 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
await lastValueFrom(service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
}));
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);;
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();;
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
})
|
||||
);
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
const httpHeaders = postSpy.mock.calls.at(-1)?.[3] as HttpHeaders;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
|
||||
it('calls data service with correct headers if all params are good', async () => {
|
||||
@ -92,15 +90,16 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
await lastValueFrom(service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
}));
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();;
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
})
|
||||
);
|
||||
const httpHeaders = postSpy.mock.calls.at(-1)?.[3] as HttpHeaders;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
|
||||
it('returns error in case of http error', async () => {
|
||||
@ -115,13 +114,13 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and succeeds', async () => {
|
||||
@ -139,18 +138,15 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
.subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
error: (err) => {
|
||||
// fails if there should be a result
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
const res = await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeFalsy();
|
||||
}
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and fails because of http error afterwards', async () => {
|
||||
@ -168,18 +164,15 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
.subscribe({
|
||||
next: (res) => {
|
||||
// fails if there should be a result
|
||||
expect(res).toBeFalsy();
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
});
|
||||
try {
|
||||
const res = await lastValueFrom(
|
||||
service.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
);
|
||||
expect(res).toBeFalsy();
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError, timer } from 'rxjs';
|
||||
import { type Observable, of, throwError, timer } from 'rxjs';
|
||||
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { AuthResult, CallbackContext } from '../callback-context';
|
||||
import type { AuthResult, CallbackContext } from '../callback-context';
|
||||
import { isNetworkError } from './error-helper';
|
||||
|
||||
@Injectable()
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
@ -42,9 +42,6 @@ describe('StateValidationCallbackHandlerService', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(StateValidationCallbackHandlerService);
|
||||
stateValidationService = TestBed.inject(StateValidationService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
@ -69,18 +66,19 @@ describe('StateValidationCallbackHandlerService', () => {
|
||||
);
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
const newCallbackContext = await lastValueFrom(service
|
||||
.callbackStateValidation(
|
||||
const newCallbackContext = await lastValueFrom(
|
||||
service.callbackStateValidation(
|
||||
{} as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(newCallbackContext).toEqual({
|
||||
validationResult: {
|
||||
idToken: 'idTokenJustForTesting',
|
||||
authResponseIsValid: true,
|
||||
},
|
||||
} as CallbackContext);
|
||||
)
|
||||
);
|
||||
expect(newCallbackContext).toEqual({
|
||||
validationResult: {
|
||||
idToken: 'idTokenJustForTesting',
|
||||
authResponseIsValid: true,
|
||||
},
|
||||
} as CallbackContext);
|
||||
});
|
||||
|
||||
it('logs error in case of an error', async () => {
|
||||
@ -96,20 +94,20 @@ expect(newCallbackContext).toEqual({
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logWarning');
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
service
|
||||
.callbackStateValidation(
|
||||
{} as CallbackContext,
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackStateValidation(
|
||||
{} as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
'authorizedCallback, token(s) validation failed, resetting. Hash: &anyFakeHash'
|
||||
);
|
||||
},
|
||||
});
|
||||
'authorizedCallback, token(s) validation failed, resetting. Hash: &anyFakeHash'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('calls resetAuthDataService.resetAuthorizationData and authStateService.updateAndPublishAuthState in case of an error', async () => {
|
||||
@ -133,24 +131,22 @@ expect(newCallbackContext).toEqual({
|
||||
);
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
service
|
||||
.callbackStateValidation(
|
||||
{ isRenewProcess: true } as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: true,
|
||||
});
|
||||
},
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackStateValidation(
|
||||
{ isRenewProcess: true } as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -43,21 +43,20 @@ export class StateValidationCallbackHandlerService {
|
||||
);
|
||||
|
||||
return callbackContext;
|
||||
} else {
|
||||
const errorMessage = `authorizedCallback, token(s) validation failed, resetting. Hash: ${this.document.location.hash}`;
|
||||
|
||||
this.loggerService.logWarning(configuration, errorMessage);
|
||||
this.resetAuthDataService.resetAuthorizationData(
|
||||
configuration,
|
||||
allConfigs
|
||||
);
|
||||
this.publishUnauthorizedState(
|
||||
callbackContext.validationResult,
|
||||
callbackContext.isRenewProcess
|
||||
);
|
||||
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
const errorMessage = `authorizedCallback, token(s) validation failed, resetting. Hash: ${this.document.location.hash}`;
|
||||
|
||||
this.loggerService.logWarning(configuration, errorMessage);
|
||||
this.resetAuthDataService.resetAuthorizationData(
|
||||
configuration,
|
||||
allConfigs
|
||||
);
|
||||
this.publishUnauthorizedState(
|
||||
callbackContext.validationResult,
|
||||
callbackContext.isRenewProcess
|
||||
);
|
||||
|
||||
throw new Error(errorMessage);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@ -30,9 +30,6 @@ describe('UserCallbackHandlerService', () => {
|
||||
mockProvider(ResetAuthDataService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(UserCallbackHandlerService);
|
||||
flowsDataService = TestBed.inject(FlowsDataService);
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@ -73,10 +70,11 @@ describe('UserCallbackHandlerService', () => {
|
||||
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('mystate', allConfigs[0]);;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('mystate', allConfigs[0]);
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false, isRenewProcess is true and refreshToken is null', async () => {
|
||||
@ -105,10 +103,11 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
];
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(spy).not.toHaveBeenCalled();;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value', async () => {
|
||||
@ -137,10 +136,11 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
];
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(spy).not.toHaveBeenCalled();;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value, id_token is false', async () => {
|
||||
@ -165,10 +165,11 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(spy).not.toHaveBeenCalled();;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is false', async () => {
|
||||
@ -202,14 +203,15 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.NotSet,
|
||||
isRenewProcess: false,
|
||||
});;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.NotSet,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls userService.getAndPersistUserDataInStore with correct params if autoUserInfo is true', async () => {
|
||||
@ -242,18 +244,17 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
.spyOn(userService, 'getAndPersistUserDataInStore')
|
||||
.mockReturnValue(of({ user: 'some_data' }));
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(
|
||||
getAndPersistUserDataInStoreSpy
|
||||
).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
false,
|
||||
'idtoken',
|
||||
'decoded'
|
||||
);;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(getAndPersistUserDataInStoreSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
false,
|
||||
'idtoken',
|
||||
'decoded'
|
||||
);
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is true', async () => {
|
||||
@ -291,14 +292,15 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
});;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls flowsDataService.setSessionState with correct params if user data is present and NOT refresh token', async () => {
|
||||
@ -333,13 +335,14 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
);
|
||||
const setSessionStateSpy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
const resultCallbackContext = await lastValueFrom(service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs));
|
||||
expect(setSessionStateSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'mystate',
|
||||
allConfigs[0]
|
||||
);;
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
const resultCallbackContext = await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(setSessionStateSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'mystate',
|
||||
allConfigs[0]
|
||||
);
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
|
||||
it('calls authStateService.publishUnauthorizedState with correct params if user info which are coming back are null', async () => {
|
||||
@ -377,22 +380,20 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve user info with error: Error: Called for userData but they were null'
|
||||
);
|
||||
},
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve user info with error: Error: Called for userData but they were null'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('calls resetAuthDataService.resetAuthorizationData if user info which are coming back are null', async () => {
|
||||
@ -430,16 +431,16 @@ expect(resultCallbackContext).toEqual(callbackContext);
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve user info with error: Error: Called for userData but they were null'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(err.message).toEqual(
|
||||
'Failed to retrieve user info with error: Error: Called for userData but they were null'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -35,6 +35,7 @@ export class UserCallbackHandlerService {
|
||||
if (!autoUserInfo) {
|
||||
if (!isRenewProcess || renewUserInfoAfterTokenRenew) {
|
||||
// userData is set to the id_token decoded, auto get user data set to false
|
||||
// biome-ignore lint/nursery/useCollapsedIf: <explanation>
|
||||
if (validationResult?.decodedIdToken) {
|
||||
this.userService.setUserDataToStore(
|
||||
validationResult.decodedIdToken,
|
||||
@ -66,7 +67,7 @@ export class UserCallbackHandlerService {
|
||||
)
|
||||
.pipe(
|
||||
switchMap((userData) => {
|
||||
if (!!userData) {
|
||||
if (userData) {
|
||||
if (!refreshToken) {
|
||||
this.flowsDataService.setSessionState(
|
||||
authResult?.session_state,
|
||||
@ -77,18 +78,17 @@ export class UserCallbackHandlerService {
|
||||
this.publishAuthState(validationResult, isRenewProcess);
|
||||
|
||||
return of(callbackContext);
|
||||
} else {
|
||||
this.resetAuthDataService.resetAuthorizationData(
|
||||
configuration,
|
||||
allConfigs
|
||||
);
|
||||
this.publishUnauthenticatedState(validationResult, isRenewProcess);
|
||||
const errorMessage = `Called for userData but they were ${userData}`;
|
||||
|
||||
this.loggerService.logWarning(configuration, errorMessage);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}
|
||||
this.resetAuthDataService.resetAuthorizationData(
|
||||
configuration,
|
||||
allConfigs
|
||||
);
|
||||
this.publishUnauthenticatedState(validationResult, isRenewProcess);
|
||||
const errorMessage = `Called for userData but they were ${userData}`;
|
||||
|
||||
this.loggerService.logWarning(configuration, errorMessage);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}),
|
||||
catchError((err) => {
|
||||
const errorMessage = `Failed to retrieve user info with error: ${err}`;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
@ -21,15 +21,13 @@ describe('Flows Data Service', () => {
|
||||
mockProvider(StoragePersistenceService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(FlowsDataService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
});
|
||||
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
|
||||
afterEach(() => {
|
||||
jasmine.clock().uninstall();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
@ -141,10 +139,11 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('codeVerifier', () => {
|
||||
it('getCodeVerifier returns value from the store', () => {
|
||||
const spy = vi
|
||||
.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('codeVerifier', { configId: 'configId1' })
|
||||
.mockReturnValue('Genesis');
|
||||
const spy = mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['codeVerifier', { configId: 'configId1' }],
|
||||
() => 'Genesis'
|
||||
);
|
||||
|
||||
const result = service.getCodeVerifier({ configId: 'configId1' });
|
||||
|
||||
@ -173,11 +172,12 @@ describe('Flows Data Service', () => {
|
||||
configId: 'configId1',
|
||||
};
|
||||
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
@ -212,11 +212,11 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('setCodeFlowInProgress', () => {
|
||||
it('set setCodeFlowInProgress to `in progress` when called', () => {
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
@ -253,23 +253,27 @@ describe('Flows Data Service', () => {
|
||||
configId: 'configId1',
|
||||
};
|
||||
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
const storageObject = {
|
||||
state: 'running',
|
||||
dateOfLaunchedProcessUtc: baseTime.toISOString(),
|
||||
};
|
||||
|
||||
vi.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('storageSilentRenewRunning', config)
|
||||
.mockReturnValue(JSON.stringify(storageObject));
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['storageSilentRenewRunning', config],
|
||||
() => JSON.stringify(storageObject)
|
||||
);
|
||||
const spyWrite = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
jasmine.clock().tick((config.silentRenewTimeoutInSeconds + 1) * 1000);
|
||||
vi.advanceTimersByTimeAsync(
|
||||
(config.silentRenewTimeoutInSeconds + 1) * 1000
|
||||
);
|
||||
|
||||
const isSilentRenewRunningResult = service.isSilentRenewRunning(config);
|
||||
|
||||
@ -287,20 +291,22 @@ describe('Flows Data Service', () => {
|
||||
configId: 'configId1',
|
||||
};
|
||||
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
const storageObject = {
|
||||
state: 'running',
|
||||
dateOfLaunchedProcessUtc: baseTime.toISOString(),
|
||||
};
|
||||
|
||||
vi.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('storageSilentRenewRunning', config)
|
||||
.mockReturnValue(JSON.stringify(storageObject));
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['storageSilentRenewRunning', config],
|
||||
() => JSON.stringify(storageObject)
|
||||
);
|
||||
const spyWrite = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
const isSilentRenewRunningResult = service.isSilentRenewRunning(config);
|
||||
@ -326,11 +332,11 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('setSilentRenewRunning', () => {
|
||||
it('set setSilentRenewRunning to `running` with lauched time when called', () => {
|
||||
jasmine.clock().uninstall();
|
||||
jasmine.clock().install();
|
||||
vi.useRealTimers();
|
||||
vi.useFakeTimers();
|
||||
const baseTime = new Date();
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
vi.setSystemTime(baseTime);
|
||||
|
||||
const storageObject = {
|
||||
state: 'running',
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import type { CallbackContext } from './callback-context';
|
||||
@ -35,9 +35,6 @@ describe('Flows Service', () => {
|
||||
mockProvider(RefreshTokenCallbackHandlerService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(FlowsService);
|
||||
codeFlowCallbackHandlerService = TestBed.inject(
|
||||
CodeFlowCallbackHandlerService
|
||||
@ -90,17 +87,22 @@ describe('Flows Service', () => {
|
||||
},
|
||||
];
|
||||
|
||||
const value = await lastValueFrom(service
|
||||
.processCodeFlowCallback('some-url1234', allConfigs[0]!, allConfigs));
|
||||
expect(value).toEqual({} as CallbackContext);;
|
||||
expect(codeFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url1234',
|
||||
allConfigs[0]
|
||||
);;
|
||||
expect(codeFlowCodeRequestSpy).toHaveBeenCalledTimes(1);;
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalledTimes(1);;
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalledTimes(1);;
|
||||
expect(callbackUserSpy).toHaveBeenCalledTimes(1);
|
||||
const value = await lastValueFrom(
|
||||
service.processCodeFlowCallback(
|
||||
'some-url1234',
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(codeFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url1234',
|
||||
allConfigs[0]
|
||||
);
|
||||
expect(codeFlowCodeRequestSpy).toHaveBeenCalledTimes(1);
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalledTimes(1);
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalledTimes(1);
|
||||
expect(callbackUserSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@ -127,17 +129,18 @@ expect(callbackUserSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
];
|
||||
|
||||
const value = await lastValueFrom(service
|
||||
.processSilentRenewCodeFlowCallback(
|
||||
const value = await lastValueFrom(
|
||||
service.processSilentRenewCodeFlowCallback(
|
||||
{} as CallbackContext,
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
));
|
||||
expect(value).toEqual({} as CallbackContext);;
|
||||
expect(codeFlowCodeRequestSpy).toHaveBeenCalled();;
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();;
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();;
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
)
|
||||
);
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(codeFlowCodeRequestSpy).toHaveBeenCalled();
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@ -164,13 +167,18 @@ expect(callbackUserSpy).toHaveBeenCalled();
|
||||
},
|
||||
];
|
||||
|
||||
const value = await lastValueFrom(service
|
||||
.processImplicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash'));
|
||||
expect(value).toEqual({} as CallbackContext);;
|
||||
expect(implicitFlowCallbackSpy).toHaveBeenCalled();;
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();;
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();;
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
const value = await lastValueFrom(
|
||||
service.processImplicitFlowCallback(
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
'any-hash'
|
||||
)
|
||||
);
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(implicitFlowCallbackSpy).toHaveBeenCalled();
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@ -203,14 +211,15 @@ expect(callbackUserSpy).toHaveBeenCalled();
|
||||
},
|
||||
];
|
||||
|
||||
const value = await lastValueFrom(service
|
||||
.processRefreshToken(allConfigs[0]!, allConfigs));
|
||||
expect(value).toEqual({} as CallbackContext);;
|
||||
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();;
|
||||
expect(refreshTokensRequestTokensSpy).toHaveBeenCalled();;
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();;
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();;
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
const value = await lastValueFrom(
|
||||
service.processRefreshToken(allConfigs[0]!, allConfigs)
|
||||
);
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();
|
||||
expect(refreshTokensRequestTokensSpy).toHaveBeenCalled();
|
||||
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { CryptoService } from '../../utils/crypto/crypto.service';
|
||||
@ -12,9 +11,6 @@ describe('RandomService Tests', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [RandomService, mockProvider(LoggerService), CryptoService],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
randomService = TestBed.inject(RandomService);
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { CryptoService } from '../../utils/crypto/crypto.service';
|
||||
|
||||
@ -37,7 +37,7 @@ export class RandomService {
|
||||
}
|
||||
|
||||
private toHex(dec: number): string {
|
||||
return ('0' + dec.toString(16)).substr(-2);
|
||||
return `0${dec.toString(16)}`.substr(-2);
|
||||
}
|
||||
|
||||
private randomString(length: number): string {
|
||||
|
@ -23,9 +23,6 @@ describe('ResetAuthDataService', () => {
|
||||
mockProvider(LoggerService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(ResetAuthDataService);
|
||||
userService = TestBed.inject(UserService);
|
||||
flowsDataService = TestBed.inject(FlowsDataService);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpResponse } from '@ngify/http';
|
||||
import { isObservable, of, throwError } from 'rxjs';
|
||||
import { EmptyError, isObservable, lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../api/data.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
@ -40,9 +40,6 @@ describe('Signin Key Data Service', () => {
|
||||
mockProvider(StoragePersistenceService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(SigninKeyDataService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
dataService = TestBed.inject(DataService);
|
||||
@ -62,11 +59,11 @@ describe('Signin Key Data Service', () => {
|
||||
);
|
||||
const result = service.getSigningKeys({ configId: 'configId1' });
|
||||
|
||||
result.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(result);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('throws error when no jwksUri given', async () => {
|
||||
@ -77,11 +74,11 @@ describe('Signin Key Data Service', () => {
|
||||
);
|
||||
const result = service.getSigningKeys({ configId: 'configId1' });
|
||||
|
||||
result.subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(result);
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('calls dataservice if jwksurl is given', async () => {
|
||||
@ -94,13 +91,15 @@ describe('Signin Key Data Service', () => {
|
||||
|
||||
const result = service.getSigningKeys({ configId: 'configId1' });
|
||||
|
||||
result.subscribe({
|
||||
complete: () => {
|
||||
try {
|
||||
await lastValueFrom(result);
|
||||
} catch (err: any) {
|
||||
if (err instanceof EmptyError) {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('someUrl', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should retry once', async () => {
|
||||
@ -116,12 +115,11 @@ describe('Signin Key Data Service', () => {
|
||||
)
|
||||
);
|
||||
|
||||
service.getSigningKeys({ configId: 'configId1' }).subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(
|
||||
service.getSigningKeys({ configId: 'configId1' })
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
});
|
||||
|
||||
it('should retry twice', async () => {
|
||||
@ -138,12 +136,11 @@ describe('Signin Key Data Service', () => {
|
||||
)
|
||||
);
|
||||
|
||||
service.getSigningKeys({ configId: 'configId1' }).subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(
|
||||
service.getSigningKeys({ configId: 'configId1' })
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
});
|
||||
|
||||
it('should fail after three tries', async () => {
|
||||
@ -161,16 +158,16 @@ describe('Signin Key Data Service', () => {
|
||||
)
|
||||
);
|
||||
|
||||
service.getSigningKeys({ configId: 'configId1' }).subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.getSigningKeys({ configId: 'configId1' }));
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleErrorGetSigningKeys', () => {
|
||||
it('keeps observable if error is catched', async () => {
|
||||
it('keeps observable if error is catched', () => {
|
||||
const result = (service as any).handleErrorGetSigningKeys(
|
||||
new HttpResponse()
|
||||
);
|
||||
@ -182,52 +179,54 @@ describe('Signin Key Data Service', () => {
|
||||
it('logs error if error is response', async () => {
|
||||
const logSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
(service as any)
|
||||
.handleErrorGetSigningKeys(
|
||||
new HttpResponse({ status: 400, statusText: 'nono' }),
|
||||
{ configId: 'configId1' }
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'400 - nono {}'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
(service as any).handleErrorGetSigningKeys(
|
||||
new HttpResponse({ status: 400, statusText: 'nono' }),
|
||||
{ configId: 'configId1' }
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'400 - nono {}'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('logs error if error is not a response', async () => {
|
||||
const logSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
(service as any)
|
||||
.handleErrorGetSigningKeys('Just some Error', { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
(service as any).handleErrorGetSigningKeys('Just some Error', {
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('logs error if error with message property is not a response', async () => {
|
||||
const logSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
(service as any)
|
||||
.handleErrorGetSigningKeys(
|
||||
{ message: 'Just some Error' },
|
||||
{ configId: 'configId1' }
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
(service as any).handleErrorGetSigningKeys(
|
||||
{ message: 'Just some Error' },
|
||||
{ configId: 'configId1' }
|
||||
)
|
||||
);
|
||||
} catch {
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { HttpResponse } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, retry } from 'rxjs/operators';
|
||||
import { DataService } from '../api/data.service';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { JwtKeys } from '../validation/jwtkeys';
|
||||
import type { JwtKeys } from '../validation/jwtkeys';
|
||||
|
||||
@Injectable()
|
||||
export class SigninKeyDataService {
|
||||
@ -62,7 +62,7 @@ export class SigninKeyDataService {
|
||||
} else {
|
||||
const { message } = errorResponse;
|
||||
|
||||
errMsg = !!message ? message : `${errorResponse}`;
|
||||
errMsg = message ? message : `${errorResponse}`;
|
||||
}
|
||||
this.loggerService.logError(currentConfiguration, errMsg);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { skip } from 'rxjs/operators';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
@ -35,15 +35,13 @@ describe('CheckSessionService', () => {
|
||||
),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
checkSessionService = TestBed.inject(CheckSessionService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
iFrameService = TestBed.inject(IFrameService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
});
|
||||
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
|
||||
afterEach(() => {
|
||||
const iFrameIdwhichshouldneverexist = window.document.getElementById(
|
||||
'idwhichshouldneverexist'
|
||||
@ -68,7 +66,7 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
it('getOrCreateIframe calls iFrameService.addIFrameToWindowBody if no Iframe exists', () => {
|
||||
vi.spyOn(iFrameService, 'addIFrameToWindowBody')();
|
||||
vi.spyOn(iFrameService, 'addIFrameToWindowBody');
|
||||
|
||||
const result = (checkSessionService as any).getOrCreateIframe({
|
||||
configId: 'configId1',
|
||||
@ -106,15 +104,18 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
it('log warning if authWellKnownEndpoints.check_session_iframe is not existing', () => {
|
||||
const spyLogWarning = vi.spyOn<any>(loggerService, 'logWarning');
|
||||
const spyLogWarning = vi.spyOn<any, any>(loggerService, 'logWarning');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
vi.spyOn<any>(loggerService, 'logDebug').mockImplementation(
|
||||
vi.spyOn<any, any>(loggerService, 'logDebug').mockImplementation(
|
||||
() => undefined
|
||||
);
|
||||
vi.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.mockReturnValue({ checkSessionIframe: undefined });
|
||||
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ checkSessionIframe: undefined })
|
||||
);
|
||||
(checkSessionService as any).init(config);
|
||||
|
||||
expect(spyLogWarning).toHaveBeenCalledExactlyOnceWith(
|
||||
@ -124,7 +125,7 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
it('start() calls pollserversession() with clientId if no scheduledheartbeat is set', () => {
|
||||
const spy = vi.spyOn<any>(checkSessionService, 'pollServerSession');
|
||||
const spy = vi.spyOn<any, any>(checkSessionService, 'pollServerSession');
|
||||
const config = { clientId: 'clientId', configId: 'configId1' };
|
||||
|
||||
checkSessionService.start(config);
|
||||
@ -133,7 +134,7 @@ describe('CheckSessionService', () => {
|
||||
|
||||
it('start() does not call pollServerSession() if scheduledHeartBeatRunning is set', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const spy = vi.spyOn<any>(checkSessionService, 'pollServerSession');
|
||||
const spy = vi.spyOn<any, any>(checkSessionService, 'pollServerSession');
|
||||
|
||||
(checkSessionService as any).scheduledHeartBeatRunning = (): void =>
|
||||
undefined;
|
||||
@ -154,7 +155,10 @@ describe('CheckSessionService', () => {
|
||||
|
||||
it('stopCheckingSession does nothing if scheduledHeartBeatRunning is not set', () => {
|
||||
(checkSessionService as any).scheduledHeartBeatRunning = null;
|
||||
const spy = vi.spyOn<any>(checkSessionService, 'clearScheduledHeartBeat');
|
||||
const spy = vi.spyOn<any, any>(
|
||||
checkSessionService,
|
||||
'clearScheduledHeartBeat'
|
||||
);
|
||||
|
||||
checkSessionService.stop();
|
||||
expect(spy).not.toHaveBeenCalledExactlyOnceWith();
|
||||
@ -187,11 +191,16 @@ describe('CheckSessionService', () => {
|
||||
|
||||
describe('pollServerSession', () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn<any>(checkSessionService, 'init').mockReturnValue(of(undefined));
|
||||
vi.spyOn<any, any>(checkSessionService, 'init').mockReturnValue(
|
||||
of(undefined)
|
||||
);
|
||||
});
|
||||
|
||||
it('increases outstandingMessages', () => {
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue({
|
||||
vi.spyOn<any, any>(
|
||||
checkSessionService,
|
||||
'getExistingIframe'
|
||||
).mockReturnValue({
|
||||
contentWindow: { postMessage: () => undefined },
|
||||
});
|
||||
const authWellKnownEndpoints = {
|
||||
@ -200,21 +209,25 @@ describe('CheckSessionService', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
)
|
||||
.withArgs('session_state', config)
|
||||
.mockReturnValue('session_state');
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
),
|
||||
['session_state', config],
|
||||
() => 'session_state'
|
||||
);
|
||||
|
||||
vi.spyOn(loggerService, 'logDebug').mockImplementation(() => undefined);
|
||||
(checkSessionService as any).pollServerSession('clientId', config);
|
||||
expect((checkSessionService as any).outstandingMessages).toBe(1);
|
||||
});
|
||||
|
||||
it('logs warning if iframe does not exist', () => {
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue(
|
||||
null
|
||||
);
|
||||
vi.spyOn<any, any>(
|
||||
checkSessionService,
|
||||
'getExistingIframe'
|
||||
).mockReturnValue(null);
|
||||
const authWellKnownEndpoints = {
|
||||
checkSessionIframe: 'https://some-testing-url.com',
|
||||
};
|
||||
@ -238,9 +251,10 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
it('logs warning if clientId is not set', () => {
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue(
|
||||
{}
|
||||
);
|
||||
vi.spyOn<any, any>(
|
||||
checkSessionService,
|
||||
'getExistingIframe'
|
||||
).mockReturnValue({});
|
||||
const authWellKnownEndpoints = {
|
||||
checkSessionIframe: 'https://some-testing-url.com',
|
||||
};
|
||||
@ -264,21 +278,24 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
it('logs debug if session_state is not set', () => {
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue(
|
||||
{}
|
||||
);
|
||||
vi.spyOn<any, any>(
|
||||
checkSessionService,
|
||||
'getExistingIframe'
|
||||
).mockReturnValue({});
|
||||
const authWellKnownEndpoints = {
|
||||
checkSessionIframe: 'https://some-testing-url.com',
|
||||
};
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
)
|
||||
.withArgs('session_state', config)
|
||||
.mockReturnValue(null);
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
),
|
||||
['session_state', config],
|
||||
() => null
|
||||
);
|
||||
|
||||
const spyLogDebug = vi
|
||||
.spyOn(loggerService, 'logDebug')
|
||||
@ -289,19 +306,23 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
it('logs debug if session_state is set but authWellKnownEndpoints are not set', () => {
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue(
|
||||
{}
|
||||
vi.spyOn(checkSessionService, 'getExistingIframe').mockReturnValue(
|
||||
{} as any
|
||||
);
|
||||
// biome-ignore lint/suspicious/noEvolvingTypes: <explanation>
|
||||
const authWellKnownEndpoints = null;
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
)
|
||||
.withArgs('session_state', config)
|
||||
.mockReturnValue('some_session_state');
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
),
|
||||
['session_state', config],
|
||||
() => 'some_session_state'
|
||||
);
|
||||
|
||||
const spyLogDebug = vi
|
||||
.spyOn(loggerService, 'logDebug')
|
||||
.mockImplementation(() => undefined);
|
||||
@ -321,7 +342,7 @@ describe('CheckSessionService', () => {
|
||||
serviceAsAny.iframeRefreshInterval = lastRefresh;
|
||||
|
||||
const result = await lastValueFrom(serviceAsAny.init());
|
||||
expect(result).toBeUndefined();
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -345,9 +366,10 @@ expect(result).toBeUndefined();
|
||||
|
||||
describe('checkSessionChanged$', () => {
|
||||
it('emits when internal event is thrown', async () => {
|
||||
const result = await lastValueFrom(checkSessionService.checkSessionChanged$
|
||||
.pipe(skip(1)));
|
||||
expect(result).toBe(true);
|
||||
const result = await lastValueFrom(
|
||||
checkSessionService.checkSessionChanged$.pipe(skip(1))
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
|
||||
const serviceAsAny = checkSessionService as any;
|
||||
|
||||
@ -355,17 +377,21 @@ expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('emits false initially', async () => {
|
||||
const result = await lastValueFrom(checkSessionService.checkSessionChanged$);
|
||||
expect(result).toBe(false);
|
||||
const result = await lastValueFrom(
|
||||
checkSessionService.checkSessionChanged$
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('emits false then true when emitted', async () => {
|
||||
const expectedResultsInOrder = [false, true];
|
||||
let counter = 0;
|
||||
|
||||
const result = await lastValueFrom(checkSessionService.checkSessionChanged$);
|
||||
expect(result).toBe(expectedResultsInOrder[counter]);;
|
||||
counter++;
|
||||
const result = await lastValueFrom(
|
||||
checkSessionService.checkSessionChanged$
|
||||
);
|
||||
expect(result).toBe(expectedResultsInOrder[counter]);
|
||||
counter++;
|
||||
|
||||
(checkSessionService as any).checkSessionChangedInternal$.next(true);
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
|
||||
@Injectable()
|
||||
@ -52,7 +52,7 @@ export class IFrameService {
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (e) {
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TestBed, fakeAsync, tick } from '@/testing';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { TestBed } from '@/testing';
|
||||
import { Observable, lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { ImplicitFlowCallbackService } from '../callback/implicit-flow-callback.service';
|
||||
@ -42,9 +42,6 @@ describe('SilentRenewService ', () => {
|
||||
FlowHelper,
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
silentRenewService = TestBed.inject(SilentRenewService);
|
||||
iFrameService = TestBed.inject(IFrameService);
|
||||
flowHelper = TestBed.inject(FlowHelper);
|
||||
@ -152,13 +149,18 @@ describe('SilentRenewService ', () => {
|
||||
const urlParts =
|
||||
'code=some-code&state=some-state&session_state=some-session-state';
|
||||
|
||||
await lastValueFrom(silentRenewService
|
||||
.codeFlowCallbackSilentRenewIframe([url, urlParts], config, allConfigs));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
expectedContext,
|
||||
config,
|
||||
allConfigs
|
||||
);
|
||||
await lastValueFrom(
|
||||
silentRenewService.codeFlowCallbackSilentRenewIframe(
|
||||
[url, urlParts],
|
||||
config,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
expectedContext,
|
||||
config,
|
||||
allConfigs
|
||||
);
|
||||
});
|
||||
|
||||
it('throws error if url has error param and resets everything on error', async () => {
|
||||
@ -185,25 +187,29 @@ expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
const url = 'url-part-1';
|
||||
const urlParts = 'error=some_error';
|
||||
|
||||
silentRenewService
|
||||
.codeFlowCallbackSilentRenewIframe([url, urlParts], config, allConfigs)
|
||||
.subscribe({
|
||||
error: (error) => {
|
||||
expect(error).toEqual(new Error('some_error'));
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(authStateServiceSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: true,
|
||||
});
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
allConfigs
|
||||
);
|
||||
expect(setNonceSpy).toHaveBeenCalledExactlyOnceWith('', config);
|
||||
expect(stopPeriodicTokenCheckSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
try {
|
||||
await lastValueFrom(
|
||||
silentRenewService.codeFlowCallbackSilentRenewIframe(
|
||||
[url, urlParts],
|
||||
config,
|
||||
allConfigs
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
expect(error).toEqual(new Error('some_error'));
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(authStateServiceSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: true,
|
||||
});
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
allConfigs
|
||||
);
|
||||
expect(setNonceSpy).toHaveBeenCalledExactlyOnceWith('', config);
|
||||
expect(stopPeriodicTokenCheckSpy).toHaveBeenCalledTimes(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -306,10 +312,12 @@ expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
const eventData = { detail: 'detail?detail2' } as CustomEvent;
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
const result = await lastValueFrom(silentRenewService.refreshSessionWithIFrameCompleted$);
|
||||
expect(result).toEqual({
|
||||
refreshToken: 'callbackContext',
|
||||
} as CallbackContext);
|
||||
const result = await lastValueFrom(
|
||||
silentRenewService.refreshSessionWithIFrameCompleted$
|
||||
);
|
||||
expect(result).toEqual({
|
||||
refreshToken: 'callbackContext',
|
||||
} as CallbackContext);
|
||||
|
||||
silentRenewService.silentRenewEventHandler(
|
||||
eventData,
|
||||
@ -352,8 +360,10 @@ expect(result).toEqual({
|
||||
const eventData = { detail: 'detail?detail2' } as CustomEvent;
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
const result = await lastValueFrom(silentRenewService.refreshSessionWithIFrameCompleted$);
|
||||
expect(result).toBeNull();
|
||||
const result = await lastValueFrom(
|
||||
silentRenewService.refreshSessionWithIFrameCompleted$
|
||||
);
|
||||
expect(result).toBeNull();
|
||||
|
||||
silentRenewService.silentRenewEventHandler(
|
||||
eventData,
|
||||
|
@ -153,7 +153,7 @@ export class SilentRenewService {
|
||||
this.flowsDataService.resetSilentRenewRunning(config);
|
||||
},
|
||||
error: (err: unknown) => {
|
||||
this.loggerService.logError(config, 'Error: ' + err);
|
||||
this.loggerService.logError(config, `Error: ${err}`);
|
||||
this.refreshSessionWithIFrameCompletedInternal$.next(null);
|
||||
this.flowsDataService.resetSilentRenewRunning(config);
|
||||
},
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
HttpTestingController,
|
||||
provideHttpClientTesting,
|
||||
} from '@ngify/http/testing';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { ConfigurationService } from '../config/config.service';
|
||||
@ -18,14 +19,14 @@ import { mockProvider } from '../testing/mock';
|
||||
import { AuthInterceptor, authInterceptor } from './auth.interceptor';
|
||||
import { ClosestMatchingRouteService } from './closest-matching-route.service';
|
||||
|
||||
describe(`AuthHttpInterceptor`, () => {
|
||||
describe('AuthHttpInterceptor', () => {
|
||||
let httpTestingController: HttpTestingController;
|
||||
let configurationService: ConfigurationService;
|
||||
let httpClient: HttpClient;
|
||||
let authStateService: AuthStateService;
|
||||
let closestMatchingRouteService: ClosestMatchingRouteService;
|
||||
|
||||
describe(`with Class Interceptor`, () => {
|
||||
describe('with Class Interceptor', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [],
|
||||
@ -51,6 +52,7 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
closestMatchingRouteService = TestBed.inject(ClosestMatchingRouteService);
|
||||
});
|
||||
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
|
||||
afterEach(() => {
|
||||
httpTestingController.verify();
|
||||
});
|
||||
@ -58,7 +60,7 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
runTests();
|
||||
});
|
||||
|
||||
describe(`with Functional Interceptor`, () => {
|
||||
describe('with Functional Interceptor', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
@ -78,6 +80,7 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
closestMatchingRouteService = TestBed.inject(ClosestMatchingRouteService);
|
||||
});
|
||||
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
|
||||
afterEach(() => {
|
||||
httpTestingController.verify();
|
||||
});
|
||||
@ -87,7 +90,7 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
|
||||
function runTests(): void {
|
||||
it('should add an Authorization header when route matches and token is present', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
const actionUrl = 'https://jsonplaceholder.typicode.com/';
|
||||
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
@ -104,7 +107,7 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
);
|
||||
|
||||
const response = await lastValueFrom(httpClient.get(actionUrl));
|
||||
expect(response).toBeTruthy();
|
||||
expect(response).toBeTruthy();
|
||||
|
||||
const httpRequest = httpTestingController.expectOne(actionUrl);
|
||||
|
||||
@ -115,7 +118,7 @@ expect(response).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when `secureRoutes` is not given', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
const actionUrl = 'https://jsonplaceholder.typicode.com/';
|
||||
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
@ -130,7 +133,7 @@ expect(response).toBeTruthy();
|
||||
);
|
||||
|
||||
const response = await lastValueFrom(httpClient.get(actionUrl));
|
||||
expect(response).toBeTruthy();
|
||||
expect(response).toBeTruthy();
|
||||
|
||||
const httpRequest = httpTestingController.expectOne(actionUrl);
|
||||
|
||||
@ -141,7 +144,7 @@ expect(response).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when no routes configured', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
const actionUrl = 'https://jsonplaceholder.typicode.com/';
|
||||
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
@ -158,7 +161,7 @@ expect(response).toBeTruthy();
|
||||
);
|
||||
|
||||
const response = await lastValueFrom(httpClient.get(actionUrl));
|
||||
expect(response).toBeTruthy();
|
||||
expect(response).toBeTruthy();
|
||||
|
||||
const httpRequest = httpTestingController.expectOne(actionUrl);
|
||||
|
||||
@ -169,7 +172,7 @@ expect(response).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when no routes configured', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
const actionUrl = 'https://jsonplaceholder.typicode.com/';
|
||||
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
@ -183,7 +186,7 @@ expect(response).toBeTruthy();
|
||||
);
|
||||
|
||||
const response = await lastValueFrom(httpClient.get(actionUrl));
|
||||
expect(response).toBeTruthy();
|
||||
expect(response).toBeTruthy();
|
||||
|
||||
const httpRequest = httpTestingController.expectOne(actionUrl);
|
||||
|
||||
@ -194,7 +197,7 @@ expect(response).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when route is configured but no token is present', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
const actionUrl = 'https://jsonplaceholder.typicode.com/';
|
||||
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
@ -209,7 +212,7 @@ expect(response).toBeTruthy();
|
||||
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('');
|
||||
|
||||
const response = await lastValueFrom(httpClient.get(actionUrl));
|
||||
expect(response).toBeTruthy();
|
||||
expect(response).toBeTruthy();
|
||||
|
||||
const httpRequest = httpTestingController.expectOne(actionUrl);
|
||||
|
||||
@ -220,14 +223,14 @@ expect(response).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when no config is present', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
const actionUrl = 'https://jsonplaceholder.typicode.com/';
|
||||
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
false
|
||||
);
|
||||
|
||||
const response = await lastValueFrom(httpClient.get(actionUrl));
|
||||
expect(response).toBeTruthy();
|
||||
expect(response).toBeTruthy();
|
||||
|
||||
const httpRequest = httpTestingController.expectOne(actionUrl);
|
||||
|
||||
@ -241,7 +244,7 @@ expect(response).toBeTruthy();
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
const actionUrl = 'https://jsonplaceholder.typicode.com/';
|
||||
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
@ -258,7 +261,7 @@ expect(response).toBeTruthy();
|
||||
});
|
||||
|
||||
const response = await lastValueFrom(httpClient.get(actionUrl));
|
||||
expect(response).toBeTruthy();
|
||||
expect(response).toBeTruthy();
|
||||
|
||||
const httpRequest = httpTestingController.expectOne(actionUrl);
|
||||
|
||||
@ -269,8 +272,8 @@ expect(response).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should add an Authorization header when multiple routes are configured and token is present', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
const actionUrl2 = `https://some-other-url.com/`;
|
||||
const actionUrl = 'https://jsonplaceholder.typicode.com/';
|
||||
const actionUrl2 = 'https://some-other-url.com/';
|
||||
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{ secureRoutes: [actionUrl, actionUrl2], configId: 'configId1' },
|
||||
@ -283,11 +286,11 @@ expect(response).toBeTruthy();
|
||||
true
|
||||
);
|
||||
|
||||
const response = await lastValueFrom(httpClient.get(actionUrl));
|
||||
expect(response).toBeTruthy();
|
||||
let response = await lastValueFrom(httpClient.get(actionUrl));
|
||||
expect(response).toBeTruthy();
|
||||
|
||||
const response = await lastValueFrom(httpClient.get(actionUrl2));
|
||||
expect(response).toBeTruthy();
|
||||
response = await lastValueFrom(httpClient.get(actionUrl2));
|
||||
expect(response).toBeTruthy();
|
||||
|
||||
const httpRequest = httpTestingController.expectOne(actionUrl);
|
||||
|
||||
|
@ -73,7 +73,7 @@ function interceptRequest(
|
||||
if (allRoutesConfiguredFlat.length === 0) {
|
||||
deps.loggerService.logDebug(
|
||||
allConfigurations[0],
|
||||
`No routes to check configured`
|
||||
'No routes to check configured'
|
||||
);
|
||||
|
||||
return next(req);
|
||||
@ -114,7 +114,7 @@ function interceptRequest(
|
||||
`'${req.url}' matches configured route '${matchingRoute}', adding token`
|
||||
);
|
||||
req = req.clone({
|
||||
headers: req.headers.set('Authorization', 'Bearer ' + token),
|
||||
headers: req.headers.set('Authorization', `Bearer ${token}`),
|
||||
});
|
||||
|
||||
return next(req);
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { ClosestMatchingRouteService } from './closest-matching-route.service';
|
||||
@ -11,9 +10,6 @@ describe('ClosestMatchingRouteService', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [ClosestMatchingRouteService, mockProvider(LoggerService)],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(ClosestMatchingRouteService);
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
||||
@Injectable()
|
||||
export class ClosestMatchingRouteService {
|
||||
|
@ -1,17 +1,20 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { AbstractLoggerService } from './abstract-logger.service';
|
||||
import type { AbstractLoggerService } from './abstract-logger.service';
|
||||
|
||||
@Injectable()
|
||||
export class ConsoleLoggerService implements AbstractLoggerService {
|
||||
logError(message: string | object, ...args: any[]): void {
|
||||
// biome-ignore lint/suspicious/noConsole: <explanation>
|
||||
console.error(message, ...args);
|
||||
}
|
||||
|
||||
logWarning(message: string | object, ...args: any[]): void {
|
||||
// biome-ignore lint/suspicious/noConsole: <explanation>
|
||||
console.warn(message, ...args);
|
||||
}
|
||||
|
||||
logDebug(message: string | object, ...args: any[]): void {
|
||||
// biome-ignore lint/suspicious/noConsole: <explanation>
|
||||
console.debug(message, ...args);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
export enum LogLevel {
|
||||
None,
|
||||
Debug,
|
||||
Warn,
|
||||
Error,
|
||||
None = 0,
|
||||
Debug = 1,
|
||||
Warn = 2,
|
||||
Error = 3,
|
||||
}
|
||||
|
@ -15,9 +15,6 @@ describe('Logger Service', () => {
|
||||
{ provide: AbstractLoggerService, useClass: ConsoleLoggerService },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { of } from 'rxjs';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
@ -31,9 +31,6 @@ describe('LoginService', () => {
|
||||
mockProvider(PopUpService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(LoginService);
|
||||
parLoginService = TestBed.inject(ParLoginService);
|
||||
popUpLoginService = TestBed.inject(PopUpLoginService);
|
||||
@ -89,6 +86,7 @@ describe('LoginService', () => {
|
||||
|
||||
it("should throw error if configuration is null and doesn't call loginPar or loginStandard", () => {
|
||||
// arrange
|
||||
// biome-ignore lint/suspicious/noEvolvingTypes: <explanation>
|
||||
const config = null;
|
||||
const loginParSpy = vi.spyOn(parLoginService, 'loginPar');
|
||||
const standardLoginSpy = vi.spyOn(standardLoginService, 'loginStandard');
|
||||
@ -119,8 +117,8 @@ describe('LoginService', () => {
|
||||
|
||||
// act
|
||||
await lastValueFrom(service.loginWithPopUp(config, [config]));
|
||||
expect(loginWithPopUpPar).toHaveBeenCalledTimes(1);;
|
||||
expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled();
|
||||
expect(loginWithPopUpPar).toHaveBeenCalledTimes(1);
|
||||
expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls standardLoginService loginstandard if usePushedAuthorisationRequests is false', async () => {
|
||||
@ -135,8 +133,8 @@ expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled();
|
||||
|
||||
// act
|
||||
await lastValueFrom(service.loginWithPopUp(config, [config]));
|
||||
expect(loginWithPopUpPar).not.toHaveBeenCalled();;
|
||||
expect(loginWithPopUpStandardSpy).toHaveBeenCalledTimes(1);
|
||||
expect(loginWithPopUpPar).not.toHaveBeenCalled();
|
||||
expect(loginWithPopUpStandardSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('stores the customParams to the storage if customParams are given', async () => {
|
||||
@ -153,15 +151,17 @@ expect(loginWithPopUpStandardSpy).toHaveBeenCalledTimes(1);
|
||||
);
|
||||
|
||||
// act
|
||||
await lastValueFrom(service.loginWithPopUp(config, [config], authOptions));
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageCustomParamsAuthRequest',
|
||||
{ custom: 'params' },
|
||||
config
|
||||
);
|
||||
await lastValueFrom(
|
||||
service.loginWithPopUp(config, [config], authOptions)
|
||||
);
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageCustomParamsAuthRequest',
|
||||
{ custom: 'params' },
|
||||
config
|
||||
);
|
||||
});
|
||||
|
||||
it('returns error if there is already a popup open', () => {
|
||||
it('returns error if there is already a popup open', async () => {
|
||||
// arrange
|
||||
const config = { usePushedAuthorisationRequests: false };
|
||||
const authOptions = { customParams: { custom: 'params' } };
|
||||
@ -175,13 +175,14 @@ expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
vi.spyOn(popUpService, 'isCurrentlyInPopup').mockReturnValue(true);
|
||||
|
||||
// act
|
||||
const result = await lastValueFrom(service
|
||||
.loginWithPopUp(config, [config], authOptions));
|
||||
expect(result).toEqual({
|
||||
errorMessage: 'There is already a popup open.',
|
||||
} as LoginResponse);;
|
||||
expect(loginWithPopUpPar).not.toHaveBeenCalled();;
|
||||
expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled();
|
||||
const result = await lastValueFrom(
|
||||
service.loginWithPopUp(config, [config], authOptions)
|
||||
);
|
||||
expect(result).toEqual({
|
||||
errorMessage: 'There is already a popup open.',
|
||||
} as LoginResponse);
|
||||
expect(loginWithPopUpPar).not.toHaveBeenCalled();
|
||||
expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { TestBed, spyOnProperty } from '@/testing';
|
||||
import { lastValueFrom, 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';
|
||||
@ -40,9 +40,6 @@ describe('ParLoginService', () => {
|
||||
mockProvider(ParService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(ParLoginService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
responseTypeValidationService = TestBed.inject(
|
||||
@ -68,7 +65,7 @@ describe('ParLoginService', () => {
|
||||
).mockReturnValue(false);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
const result = service.loginPar({});
|
||||
const result = await lastValueFrom(service.loginPar({}));
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
@ -89,10 +86,12 @@ describe('ParLoginService', () => {
|
||||
.spyOn(parService, 'postParRequest')
|
||||
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
|
||||
|
||||
const result = service.loginPar({
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
});
|
||||
const result = await lastValueFrom(
|
||||
service.loginPar({
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
})
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
@ -117,9 +116,11 @@ describe('ParLoginService', () => {
|
||||
.spyOn(parService, 'postParRequest')
|
||||
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
|
||||
|
||||
const result = service.loginPar(config, {
|
||||
customParams: { some: 'thing' },
|
||||
});
|
||||
const result = await lastValueFrom(
|
||||
service.loginPar(config, {
|
||||
customParams: { some: 'thing' },
|
||||
})
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
|
||||
@ -148,7 +149,7 @@ describe('ParLoginService', () => {
|
||||
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue('');
|
||||
const spy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
const result = service.loginPar(config);
|
||||
const result = await lastValueFrom(service.loginPar(config));
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
@ -179,7 +180,7 @@ describe('ParLoginService', () => {
|
||||
);
|
||||
const spy = vi.spyOn(redirectService, 'redirectTo');
|
||||
|
||||
service.loginPar(config, authOptions);
|
||||
await lastValueFrom(service.loginPar(config, authOptions));
|
||||
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-par-url');
|
||||
});
|
||||
@ -206,7 +207,7 @@ describe('ParLoginService', () => {
|
||||
'some-par-url'
|
||||
);
|
||||
const redirectToSpy = vi.spyOn(redirectService, 'redirectTo');
|
||||
const spy = jasmine.createSpy();
|
||||
const spy = vi.fn();
|
||||
const urlHandler = (url: any): void => {
|
||||
spy(url);
|
||||
};
|
||||
@ -228,12 +229,12 @@ describe('ParLoginService', () => {
|
||||
const config = {};
|
||||
const allConfigs = [config];
|
||||
|
||||
service.loginWithPopUpPar(config, allConfigs).subscribe({
|
||||
error: (err) => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err.message).toBe('Invalid response type!');
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(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 () => {
|
||||
@ -256,14 +257,14 @@ describe('ParLoginService', () => {
|
||||
.spyOn(parService, 'postParRequest')
|
||||
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
|
||||
|
||||
service.loginWithPopUpPar(config, allConfigs).subscribe({
|
||||
error: (err) => {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(err.message).toBe(
|
||||
"Could not create URL with param requestUri: 'url'"
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(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 () => {
|
||||
@ -286,20 +287,20 @@ describe('ParLoginService', () => {
|
||||
.spyOn(parService, 'postParRequest')
|
||||
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
|
||||
|
||||
service
|
||||
.loginWithPopUpPar(config, allConfigs, {
|
||||
try {
|
||||
await lastValueFrom(
|
||||
service.loginWithPopUpPar(config, allConfigs, {
|
||||
customParams: { some: 'thing' },
|
||||
})
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
|
||||
customParams: { some: 'thing' },
|
||||
})
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
|
||||
customParams: { some: 'thing' },
|
||||
});
|
||||
expect(err.message).toBe(
|
||||
"Could not create URL with param requestUri: 'url'"
|
||||
);
|
||||
},
|
||||
});
|
||||
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 () => {
|
||||
@ -324,18 +325,18 @@ describe('ParLoginService', () => {
|
||||
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue('');
|
||||
const spy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
service
|
||||
.loginWithPopUpPar(config, allConfigs, {
|
||||
customParams: { some: 'thing' },
|
||||
})
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toBe(
|
||||
"Could not create URL with param requestUri: 'url'"
|
||||
);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
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 () => {
|
||||
@ -369,11 +370,11 @@ describe('ParLoginService', () => {
|
||||
const spy = vi.spyOn(popupService, 'openPopUp');
|
||||
|
||||
await lastValueFrom(service.loginWithPopUpPar(config, allConfigs));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-par-url',
|
||||
undefined,
|
||||
config
|
||||
);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-par-url',
|
||||
undefined,
|
||||
config
|
||||
);
|
||||
});
|
||||
|
||||
it('returns correct properties if URL is received', async () => {
|
||||
@ -418,19 +419,21 @@ expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
|
||||
spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
|
||||
|
||||
const result = await lastValueFrom(service.loginWithPopUpPar(config, allConfigs));
|
||||
expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
allConfigs,
|
||||
'someUrl'
|
||||
);;
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: true,
|
||||
configId: 'configId1',
|
||||
idToken: '',
|
||||
userData: { any: 'userData' },
|
||||
accessToken: 'anyAccessToken',
|
||||
});
|
||||
const result = await lastValueFrom(
|
||||
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 () => {
|
||||
@ -462,16 +465,18 @@ expect(result).toEqual({
|
||||
|
||||
spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
|
||||
|
||||
const result = await lastValueFrom(service.loginWithPopUpPar(config, allConfigs));
|
||||
expect(checkAuthSpy).not.toHaveBeenCalled();;
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
errorMessage: 'User closed popup',
|
||||
configId: 'configId1',
|
||||
idToken: '',
|
||||
userData: null,
|
||||
accessToken: '',
|
||||
});
|
||||
const result = await lastValueFrom(
|
||||
service.loginWithPopUpPar(config, allConfigs)
|
||||
);
|
||||
expect(checkAuthSpy).not.toHaveBeenCalled();
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
errorMessage: 'User closed popup',
|
||||
configId: 'configId1',
|
||||
idToken: '',
|
||||
userData: null,
|
||||
accessToken: '',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { switchMap, take } from 'rxjs/operators';
|
||||
import { map, shareReplay, switchMap, take } from 'rxjs/operators';
|
||||
import type { AuthOptions } from '../../auth-options';
|
||||
import { CheckAuthService } from '../../auth-state/check-auth.service';
|
||||
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
|
||||
@ -39,7 +39,7 @@ export class ParLoginService {
|
||||
loginPar(
|
||||
configuration: OpenIdConfiguration,
|
||||
authOptions?: AuthOptions
|
||||
): void {
|
||||
): Observable<void> {
|
||||
if (
|
||||
!this.responseTypeValidationService.hasConfigValidResponseType(
|
||||
configuration
|
||||
@ -55,38 +55,53 @@ export class ParLoginService {
|
||||
'BEGIN Authorize OIDC Flow, no auth data'
|
||||
);
|
||||
|
||||
this.authWellKnownService
|
||||
const result$ = this.authWellKnownService
|
||||
.queryAndStoreAuthWellKnownEndPoints(configuration)
|
||||
.pipe(
|
||||
switchMap(() =>
|
||||
this.parService.postParRequest(configuration, authOptions)
|
||||
)
|
||||
)
|
||||
.subscribe((response) => {
|
||||
this.loggerService.logDebug(configuration, 'par response: ', response);
|
||||
),
|
||||
map(() => {
|
||||
(response) => {
|
||||
this.loggerService.logDebug(
|
||||
configuration,
|
||||
'par response: ',
|
||||
response
|
||||
);
|
||||
|
||||
const url = this.urlService.getAuthorizeParUrl(
|
||||
response.requestUri,
|
||||
configuration
|
||||
);
|
||||
const url = this.urlService.getAuthorizeParUrl(
|
||||
response.requestUri,
|
||||
configuration
|
||||
);
|
||||
|
||||
this.loggerService.logDebug(configuration, 'par request url: ', url);
|
||||
this.loggerService.logDebug(
|
||||
configuration,
|
||||
'par request url: ',
|
||||
url
|
||||
);
|
||||
|
||||
if (!url) {
|
||||
this.loggerService.logError(
|
||||
configuration,
|
||||
`Could not create URL with param ${response.requestUri}: '${url}'`
|
||||
);
|
||||
if (!url) {
|
||||
this.loggerService.logError(
|
||||
configuration,
|
||||
`Could not create URL with param ${response.requestUri}: '${url}'`
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (authOptions?.urlHandler) {
|
||||
authOptions.urlHandler(url);
|
||||
} else {
|
||||
this.redirectService.redirectTo(url);
|
||||
}
|
||||
});
|
||||
if (authOptions?.urlHandler) {
|
||||
authOptions.urlHandler(url);
|
||||
} else {
|
||||
this.redirectService.redirectTo(url);
|
||||
}
|
||||
};
|
||||
}),
|
||||
shareReplay(1)
|
||||
);
|
||||
|
||||
result$.subscribe();
|
||||
|
||||
return result$;
|
||||
}
|
||||
|
||||
loginWithPopUpPar(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
@ -26,9 +26,6 @@ describe('ParService', () => {
|
||||
mockProvider(StoragePersistenceService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(ParService);
|
||||
dataService = TestBed.inject(DataService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
@ -50,13 +47,13 @@ describe('ParService', () => {
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => null
|
||||
);
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toBe(
|
||||
'Could not read PAR endpoint because authWellKnownEndPoints are not given'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.postParRequest({ configId: 'configId1' }));
|
||||
} catch (err: any) {
|
||||
expect(err.message).toBe(
|
||||
'Could not read PAR endpoint because authWellKnownEndPoints are not given'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('throws error if par endpoint does not exist in storage', async () => {
|
||||
@ -68,13 +65,13 @@ describe('ParService', () => {
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ some: 'thing' })
|
||||
);
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toBe(
|
||||
'Could not read PAR endpoint from authWellKnownEndpoints'
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.postParRequest({ configId: 'configId1' }));
|
||||
} catch (err: any) {
|
||||
expect(err.message).toBe(
|
||||
'Could not read PAR endpoint from authWellKnownEndpoints'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('calls data service with correct params', async () => {
|
||||
@ -92,12 +89,12 @@ describe('ParService', () => {
|
||||
.mockReturnValue(of({}));
|
||||
|
||||
await lastValueFrom(service.postParRequest({ configId: 'configId1' }));
|
||||
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'parEndpoint',
|
||||
'some-url123',
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'parEndpoint',
|
||||
'some-url123',
|
||||
{ configId: 'configId1' },
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
});
|
||||
|
||||
it('Gives back correct object properties', async () => {
|
||||
@ -112,8 +109,10 @@ expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
of({ expires_in: 123, request_uri: 'request_uri' })
|
||||
);
|
||||
const result = await lastValueFrom(service.postParRequest({ configId: 'configId1' }));
|
||||
expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
const result = await lastValueFrom(
|
||||
service.postParRequest({ configId: 'configId1' })
|
||||
);
|
||||
expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
});
|
||||
|
||||
it('throws error if data service has got an error', async () => {
|
||||
@ -130,18 +129,18 @@ expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toBe(
|
||||
'There was an error on ParService postParRequest'
|
||||
);
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'There was an error on ParService postParRequest',
|
||||
expect.any(Error)
|
||||
);
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.postParRequest({ configId: 'configId1' }));
|
||||
} catch (err: any) {
|
||||
expect(err.message).toBe(
|
||||
'There was an error on ParService postParRequest'
|
||||
);
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'There was an error on ParService postParRequest',
|
||||
expect.any(Error)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should retry once', async () => {
|
||||
@ -160,12 +159,11 @@ expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
)
|
||||
);
|
||||
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(
|
||||
service.postParRequest({ configId: 'configId1' })
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
});
|
||||
|
||||
it('should retry twice', async () => {
|
||||
@ -185,12 +183,11 @@ expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
)
|
||||
);
|
||||
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe({
|
||||
next: (res) => {
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(
|
||||
service.postParRequest({ configId: 'configId1' })
|
||||
);
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
});
|
||||
|
||||
it('should fail after three tries', async () => {
|
||||
@ -211,11 +208,11 @@ expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
)
|
||||
);
|
||||
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.postParRequest({ configId: 'configId1' }));
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, map, retry, switchMap } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { AuthOptions } from '../../auth-options';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { AuthOptions } from '../../auth-options';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { ParResponse } from './par-response';
|
||||
import type { ParResponse } from './par-response';
|
||||
|
||||
@Injectable()
|
||||
export class ParService {
|
||||
@ -74,7 +74,7 @@ export class ParService {
|
||||
};
|
||||
}),
|
||||
catchError((error) => {
|
||||
const errorMessage = `There was an error on ParService postParRequest`;
|
||||
const errorMessage = 'There was an error on ParService postParRequest';
|
||||
|
||||
this.loggerService.logError(configuration, errorMessage, error);
|
||||
|
||||
|
@ -59,12 +59,14 @@ describe('PopUpLoginService', () => {
|
||||
).mockReturnValue(false);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
popUpLoginService.loginWithPopUpStandard(config, [config]).subscribe({
|
||||
error: (err) => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err.message).toBe('Invalid response type!');
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(
|
||||
popUpLoginService.loginWithPopUpStandard(config, [config])
|
||||
);
|
||||
} catch (err: any) {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err.message).toBe('Invalid response type!');
|
||||
}
|
||||
});
|
||||
|
||||
it('calls urlService.getAuthorizeUrl() if everything fits', async () => {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { TestBed, fakeAsync, tick } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { TestBed, spyOnProperty } from '@/testing';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { type MockInstance, vi } from 'vitest';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
@ -113,7 +114,7 @@ describe('PopUpService', () => {
|
||||
};
|
||||
|
||||
const result = await lastValueFrom(popUpService.result$);
|
||||
expect(result).toBe(popupResult);
|
||||
expect(result).toBe(popupResult);
|
||||
|
||||
(popUpService as any).resultInternal$.next(popupResult);
|
||||
});
|
||||
@ -122,7 +123,7 @@ expect(result).toBe(popupResult);
|
||||
describe('openPopup', () => {
|
||||
it('popup opens with parameters and default options', async () => {
|
||||
// arrange
|
||||
const popupSpy = vi.spyOn(window, 'open').and.callFake(
|
||||
const popupSpy = vi.spyOn(window, 'open').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
closed: true,
|
||||
@ -143,7 +144,7 @@ expect(result).toBe(popupResult);
|
||||
|
||||
it('popup opens with parameters and passed options', async () => {
|
||||
// arrange
|
||||
const popupSpy = vi.spyOn(window, 'open').and.callFake(
|
||||
const popupSpy = vi.spyOn(window, 'open').mockImplementation(
|
||||
() =>
|
||||
({
|
||||
closed: true,
|
||||
@ -180,9 +181,9 @@ expect(result).toBe(popupResult);
|
||||
describe('popup closed', () => {
|
||||
let popup: Window;
|
||||
let popupResult: PopupResult;
|
||||
let cleanUpSpy: jasmine.Spy;
|
||||
let cleanUpSpy: MockInstance;
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
popup = {
|
||||
closed: false,
|
||||
close: () => undefined,
|
||||
@ -190,12 +191,12 @@ expect(result).toBe(popupResult);
|
||||
|
||||
vi.spyOn(window, 'open').mockReturnValue(popup);
|
||||
|
||||
cleanUpSpy = vi.spyOn(popUpService as any, 'cleanUp')();
|
||||
cleanUpSpy = vi.spyOn(popUpService as any, 'cleanUp');
|
||||
|
||||
popupResult = {} as PopupResult;
|
||||
|
||||
const result = await lastValueFrom(popUpService.result$);
|
||||
(popupResult = result)
|
||||
popupResult = result;
|
||||
});
|
||||
|
||||
it('message received with data', async () => {
|
||||
@ -203,8 +204,10 @@ expect(result).toBe(popupResult);
|
||||
return;
|
||||
};
|
||||
|
||||
vi.spyOn(window, 'addEventListener').and.callFake(
|
||||
(_: any, func: any) => (listener = func)
|
||||
vi.spyOn(window, 'addEventListener').mockImplementation(
|
||||
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
|
||||
// biome-ignore lint/complexity/noVoid: <explanation>
|
||||
(_: any, func: any) => void (listener = func)
|
||||
);
|
||||
|
||||
popUpService.openPopUp('url', {}, { configId: 'configId1' });
|
||||
@ -214,7 +217,7 @@ expect(result).toBe(popupResult);
|
||||
|
||||
listener(new MessageEvent('message', { data: 'some-url1111' }));
|
||||
|
||||
tick(200);
|
||||
await vi.advanceTimersByTimeAsync(200);
|
||||
|
||||
expect(popupResult).toEqual({
|
||||
userClosed: false,
|
||||
@ -230,7 +233,8 @@ expect(result).toBe(popupResult);
|
||||
return;
|
||||
};
|
||||
|
||||
vi.spyOn(window, 'addEventListener').and.callFake(
|
||||
vi.spyOn(window, 'addEventListener').mockImplementation(
|
||||
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
|
||||
(_: any, func: any) => (listener = func)
|
||||
);
|
||||
const nextSpy = vi.spyOn((popUpService as any).resultInternal$, 'next');
|
||||
@ -242,7 +246,7 @@ expect(result).toBe(popupResult);
|
||||
|
||||
listener(new MessageEvent('message', { data: null }));
|
||||
|
||||
tick(200);
|
||||
vi.advanceTimersByTimeAsync(200);
|
||||
|
||||
expect(popupResult).toEqual({} as PopupResult);
|
||||
expect(cleanUpSpy).toHaveBeenCalled();
|
||||
@ -257,7 +261,7 @@ expect(result).toBe(popupResult);
|
||||
|
||||
(popup as any).closed = true;
|
||||
|
||||
tick(200);
|
||||
await vi.advanceTimersByTimeAsync(200);
|
||||
|
||||
expect(popupResult).toEqual({
|
||||
userClosed: true,
|
||||
@ -278,6 +282,8 @@ expect(result).toBe(popupResult);
|
||||
// act
|
||||
popUpService.sendMessageToMainWindow('', {});
|
||||
|
||||
await vi.advanceTimersToNextFrame();
|
||||
|
||||
// assert
|
||||
expect(sendMessageSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { type Observable, Subject } from 'rxjs';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { PopupOptions } from './popup-options';
|
||||
import { PopupResult } from './popup-result';
|
||||
import type { PopupOptions } from './popup-options';
|
||||
import type { PopupResult } from './popup-result';
|
||||
|
||||
@Injectable()
|
||||
export class PopUpService {
|
||||
@ -90,7 +90,7 @@ export class PopUpService {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loggerService.logDebug(config, 'Opened popup with url ' + url);
|
||||
this.loggerService.logDebug(config, `Opened popup with url ${url}`);
|
||||
|
||||
const listener = (event: MessageEvent): void => {
|
||||
if (!event?.data || typeof event.data !== 'string') {
|
||||
@ -104,7 +104,7 @@ export class PopUpService {
|
||||
|
||||
this.loggerService.logDebug(
|
||||
config,
|
||||
'Received message from popup with url ' + event.data
|
||||
`Received message from popup with url ${event.data}`
|
||||
);
|
||||
|
||||
this.resultInternal$.next({ userClosed: false, receivedUrl: event.data });
|
||||
|
@ -18,9 +18,6 @@ describe('ResponseTypeValidationService', () => {
|
||||
mockProvider(FlowHelper),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
responseTypeValidationService = TestBed.inject(
|
||||
ResponseTypeValidationService
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { FlowHelper } from '../../utils/flowHelper/flow-helper.service';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TestBed, fakeAsync, tick } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { TestBed } from '@/testing';
|
||||
import { lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
|
||||
import { FlowsDataService } from '../../flows/flows-data.service';
|
||||
@ -32,9 +32,6 @@ describe('StandardLoginService', () => {
|
||||
mockProvider(FlowsDataService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
standardLoginService = TestBed.inject(StandardLoginService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
responseTypeValidationService = TestBed.inject(
|
||||
@ -59,9 +56,11 @@ describe('StandardLoginService', () => {
|
||||
).mockReturnValue(false);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
const result = standardLoginService.loginStandard({
|
||||
configId: 'configId1',
|
||||
});
|
||||
const result = await lastValueFrom(
|
||||
standardLoginService.loginStandard({
|
||||
configId: 'configId1',
|
||||
})
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
@ -84,7 +83,9 @@ describe('StandardLoginService', () => {
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
const flowsDataSpy = vi.spyOn(flowsDataService, 'setCodeFlowInProgress');
|
||||
|
||||
const result = standardLoginService.loginStandard(config);
|
||||
const result = await lastValueFrom(
|
||||
standardLoginService.loginStandard(config)
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
@ -106,7 +107,9 @@ describe('StandardLoginService', () => {
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
|
||||
const result = standardLoginService.loginStandard(config);
|
||||
const result = await lastValueFrom(
|
||||
standardLoginService.loginStandard(config)
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
@ -126,10 +129,10 @@ describe('StandardLoginService', () => {
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
const redirectSpy = vi.spyOn(redirectService, 'redirectTo')();
|
||||
const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
|
||||
|
||||
standardLoginService.loginStandard(config);
|
||||
tick();
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someUrl');
|
||||
});
|
||||
|
||||
@ -151,13 +154,13 @@ describe('StandardLoginService', () => {
|
||||
const redirectSpy = vi
|
||||
.spyOn(redirectService, 'redirectTo')
|
||||
.mockImplementation(() => undefined);
|
||||
const spy = jasmine.createSpy();
|
||||
const spy = vi.fn();
|
||||
const urlHandler = (url: any): void => {
|
||||
spy(url);
|
||||
};
|
||||
|
||||
standardLoginService.loginStandard(config, { urlHandler });
|
||||
tick();
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('someUrl');
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -183,7 +186,7 @@ describe('StandardLoginService', () => {
|
||||
);
|
||||
|
||||
standardLoginService.loginStandard(config, {});
|
||||
tick();
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
@ -212,7 +215,7 @@ describe('StandardLoginService', () => {
|
||||
standardLoginService.loginStandard(config, {
|
||||
customParams: { to: 'add', as: 'well' },
|
||||
});
|
||||
tick();
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someUrl');
|
||||
expect(getAuthorizeUrlSpy).toHaveBeenCalledExactlyOnceWith(config, {
|
||||
customParams: { to: 'add', as: 'well' },
|
||||
@ -241,7 +244,7 @@ describe('StandardLoginService', () => {
|
||||
.mockImplementation(() => undefined);
|
||||
|
||||
standardLoginService.loginStandard(config);
|
||||
tick();
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
'Could not create URL',
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { AuthOptions } from '../../auth-options';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, map, shareReplay, switchMap } from 'rxjs';
|
||||
import type { AuthOptions } from '../../auth-options';
|
||||
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { FlowsDataService } from '../../flows/flows-data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { RedirectService } from '../../utils/redirect/redirect.service';
|
||||
@ -27,7 +28,7 @@ export class StandardLoginService {
|
||||
loginStandard(
|
||||
configuration: OpenIdConfiguration,
|
||||
authOptions?: AuthOptions
|
||||
): void {
|
||||
): Observable<void> {
|
||||
if (
|
||||
!this.responseTypeValidationService.hasConfigValidResponseType(
|
||||
configuration
|
||||
@ -44,32 +45,37 @@ export class StandardLoginService {
|
||||
);
|
||||
this.flowsDataService.setCodeFlowInProgress(configuration);
|
||||
|
||||
this.authWellKnownService
|
||||
const result$ = this.authWellKnownService
|
||||
.queryAndStoreAuthWellKnownEndPoints(configuration)
|
||||
.subscribe(() => {
|
||||
const { urlHandler } = authOptions || {};
|
||||
.pipe(
|
||||
switchMap(() => {
|
||||
this.flowsDataService.resetSilentRenewRunning(configuration);
|
||||
|
||||
this.flowsDataService.resetSilentRenewRunning(configuration);
|
||||
return this.urlService.getAuthorizeUrl(configuration, authOptions);
|
||||
}),
|
||||
map((url) => {
|
||||
const { urlHandler } = authOptions || {};
|
||||
if (!url) {
|
||||
this.loggerService.logError(
|
||||
configuration,
|
||||
'Could not create URL',
|
||||
url
|
||||
);
|
||||
|
||||
this.urlService
|
||||
.getAuthorizeUrl(configuration, authOptions)
|
||||
.subscribe((url) => {
|
||||
if (!url) {
|
||||
this.loggerService.logError(
|
||||
configuration,
|
||||
'Could not create URL',
|
||||
url
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (urlHandler) {
|
||||
urlHandler(url);
|
||||
} else {
|
||||
this.redirectService.redirectTo(url);
|
||||
}
|
||||
}),
|
||||
shareReplay(1)
|
||||
);
|
||||
|
||||
if (urlHandler) {
|
||||
urlHandler(url);
|
||||
} else {
|
||||
this.redirectService.redirectTo(url);
|
||||
}
|
||||
});
|
||||
});
|
||||
result$.subscribe();
|
||||
|
||||
return result$;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import type { HttpHeaders } from '@ngify/http';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { Observable, lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../api/data.service';
|
||||
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
|
||||
@ -35,9 +35,6 @@ describe('Logout and Revoke Service', () => {
|
||||
mockProvider(RedirectService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(LogoffRevocationService);
|
||||
dataService = TestBed.inject(DataService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
@ -124,8 +121,8 @@ describe('Logout and Revoke Service', () => {
|
||||
|
||||
// Act
|
||||
const result = await lastValueFrom(service.revokeAccessToken(config));
|
||||
expect(result).toEqual({ data: 'anything' });;
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(result).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('loggs error when request is negative', async () => {
|
||||
@ -144,12 +141,12 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
);
|
||||
|
||||
// Act
|
||||
service.revokeAccessToken(config).subscribe({
|
||||
error: (err) => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.revokeAccessToken(config));
|
||||
} catch (err: any) {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('should retry once', async () => {
|
||||
@ -170,14 +167,10 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
)
|
||||
);
|
||||
|
||||
service.revokeAccessToken(config).subscribe({
|
||||
next: (res) => {
|
||||
// Assert
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(service.revokeAccessToken(config));
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should retry twice', async () => {
|
||||
@ -199,14 +192,10 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
)
|
||||
);
|
||||
|
||||
service.revokeAccessToken(config).subscribe({
|
||||
next: (res) => {
|
||||
// Assert
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(service.revokeAccessToken(config));
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should fail after three tries', async () => {
|
||||
@ -229,12 +218,12 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
)
|
||||
);
|
||||
|
||||
service.revokeAccessToken(config).subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.revokeAccessToken(config));
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -309,8 +298,8 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
|
||||
// Act
|
||||
const result = await lastValueFrom(service.revokeRefreshToken(config));
|
||||
expect(result).toEqual({ data: 'anything' });;
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(result).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('loggs error when request is negative', async () => {
|
||||
@ -329,12 +318,12 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
);
|
||||
|
||||
// Act
|
||||
service.revokeRefreshToken(config).subscribe({
|
||||
error: (err) => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.revokeRefreshToken(config));
|
||||
} catch (err: any) {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('should retry once', async () => {
|
||||
@ -355,14 +344,10 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
)
|
||||
);
|
||||
|
||||
service.revokeRefreshToken(config).subscribe({
|
||||
next: (res) => {
|
||||
// Assert
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(service.revokeRefreshToken(config));
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should retry twice', async () => {
|
||||
@ -384,14 +369,10 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
)
|
||||
);
|
||||
|
||||
service.revokeRefreshToken(config).subscribe({
|
||||
next: (res) => {
|
||||
// Assert
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
const res = await lastValueFrom(service.revokeRefreshToken(config));
|
||||
expect(res).toBeTruthy();
|
||||
expect(res).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should fail after three tries', async () => {
|
||||
@ -414,12 +395,12 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
)
|
||||
);
|
||||
|
||||
service.revokeRefreshToken(config).subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.revokeRefreshToken(config));
|
||||
} catch (err: any) {
|
||||
expect(err).toBeTruthy();
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -439,7 +420,7 @@ expect(loggerSpy).toHaveBeenCalled();
|
||||
|
||||
// Assert
|
||||
await lastValueFrom(result$);
|
||||
expect(serverStateChangedSpy).not.toHaveBeenCalled();
|
||||
expect(serverStateChangedSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('logs and returns if `serverStateChanged` is true', async () => {
|
||||
@ -455,13 +436,13 @@ expect(serverStateChangedSpy).not.toHaveBeenCalled();
|
||||
|
||||
// Assert
|
||||
await lastValueFrom(result$);
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls urlHandler if urlhandler is passed', async () => {
|
||||
// Arrange
|
||||
vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
|
||||
const spy = jasmine.createSpy();
|
||||
const spy = vi.fn();
|
||||
const urlHandler = (url: string): void => {
|
||||
spy(url);
|
||||
};
|
||||
@ -481,9 +462,9 @@ expect(redirectSpy).not.toHaveBeenCalled();
|
||||
|
||||
// Assert
|
||||
await lastValueFrom(result$);
|
||||
expect(redirectSpy).not.toHaveBeenCalled();;
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('someValue');;
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls redirect service if no logoutOptions are passed', async () => {
|
||||
@ -502,7 +483,7 @@ expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
|
||||
// Assert
|
||||
await lastValueFrom(result$);
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
});
|
||||
|
||||
it('calls redirect service if logoutOptions are passed and method is GET', async () => {
|
||||
@ -521,7 +502,7 @@ expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
|
||||
// Assert
|
||||
await lastValueFrom(result$);
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
});
|
||||
|
||||
it('calls dataservice post if logoutOptions are passed and method is POST', async () => {
|
||||
@ -553,22 +534,22 @@ expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
|
||||
// Assert
|
||||
await lastValueFrom(result$);
|
||||
expect(redirectSpy).not.toHaveBeenCalled();;
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url',
|
||||
{
|
||||
id_token_hint: 'id-token',
|
||||
client_id: 'clientId',
|
||||
post_logout_redirect_uri: 'post-logout-redirect-url',
|
||||
},
|
||||
config,
|
||||
expect.anything()
|
||||
);;
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();;
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url',
|
||||
{
|
||||
id_token_hint: 'id-token',
|
||||
client_id: 'clientId',
|
||||
post_logout_redirect_uri: 'post-logout-redirect-url',
|
||||
},
|
||||
config,
|
||||
expect.anything()
|
||||
);
|
||||
const httpHeaders = postSpy.mock.calls.at(-1)?.[3] as HttpHeaders;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
|
||||
it('calls dataservice post if logoutOptions with customParams are passed and method is POST', async () => {
|
||||
@ -605,25 +586,25 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
|
||||
// Assert
|
||||
await lastValueFrom(result$);
|
||||
expect(redirectSpy).not.toHaveBeenCalled();;
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url',
|
||||
{
|
||||
id_token_hint: 'id-token',
|
||||
client_id: 'clientId',
|
||||
post_logout_redirect_uri: 'post-logout-redirect-url',
|
||||
state: 'state',
|
||||
logout_hint: 'logoutHint',
|
||||
ui_locales: 'de fr en',
|
||||
},
|
||||
config,
|
||||
expect.anything()
|
||||
);;
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();;
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url',
|
||||
{
|
||||
id_token_hint: 'id-token',
|
||||
client_id: 'clientId',
|
||||
post_logout_redirect_uri: 'post-logout-redirect-url',
|
||||
state: 'state',
|
||||
logout_hint: 'logoutHint',
|
||||
ui_locales: 'de fr en',
|
||||
},
|
||||
config,
|
||||
expect.anything()
|
||||
);
|
||||
const httpHeaders = postSpy.mock.calls.at(-1)?.[3] as HttpHeaders;
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -667,8 +648,8 @@ expect(httpHeaders.get('Content-Type')).toBe(
|
||||
|
||||
// Act
|
||||
await lastValueFrom(service.logoffAndRevokeTokens(config, [config]));
|
||||
expect(revokeRefreshTokenSpy).toHaveBeenCalled();;
|
||||
expect(revokeAccessTokenSpy).toHaveBeenCalled();
|
||||
expect(revokeRefreshTokenSpy).toHaveBeenCalled();
|
||||
expect(revokeAccessTokenSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('logs error when revokeaccesstoken throws an error', async () => {
|
||||
@ -694,12 +675,12 @@ expect(revokeAccessTokenSpy).toHaveBeenCalled();
|
||||
);
|
||||
|
||||
// Act
|
||||
service.logoffAndRevokeTokens(config, [config]).subscribe({
|
||||
error: (err) => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.logoffAndRevokeTokens(config, [config]));
|
||||
} catch (err: any) {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('calls logoff in case of success', async () => {
|
||||
@ -720,7 +701,7 @@ expect(revokeAccessTokenSpy).toHaveBeenCalled();
|
||||
|
||||
// Act
|
||||
await lastValueFrom(service.logoffAndRevokeTokens(config, [config]));
|
||||
expect(logoffSpy).toHaveBeenCalled();
|
||||
expect(logoffSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls logoff with urlhandler in case of success', async () => {
|
||||
@ -741,11 +722,12 @@ expect(logoffSpy).toHaveBeenCalled();
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
await lastValueFrom(service
|
||||
.logoffAndRevokeTokens(config, [config], { urlHandler }));
|
||||
expect(logoffSpy).toHaveBeenCalledExactlyOnceWith(config, [config], {
|
||||
urlHandler,
|
||||
});
|
||||
await lastValueFrom(
|
||||
service.logoffAndRevokeTokens(config, [config], { urlHandler })
|
||||
);
|
||||
expect(logoffSpy).toHaveBeenCalledExactlyOnceWith(config, [config], {
|
||||
urlHandler,
|
||||
});
|
||||
});
|
||||
|
||||
it('calls revokeAccessToken when storage does not hold a refreshtoken', async () => {
|
||||
@ -768,8 +750,8 @@ expect(logoffSpy).toHaveBeenCalledExactlyOnceWith(config, [config], {
|
||||
|
||||
// Act
|
||||
await lastValueFrom(service.logoffAndRevokeTokens(config, [config]));
|
||||
expect(revokeRefreshTokenSpy).not.toHaveBeenCalled();;
|
||||
expect(revokeAccessTokenSpy).toHaveBeenCalled();
|
||||
expect(revokeRefreshTokenSpy).not.toHaveBeenCalled();
|
||||
expect(revokeAccessTokenSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('logs error when revokeaccesstoken throws an error', async () => {
|
||||
@ -791,12 +773,12 @@ expect(revokeAccessTokenSpy).toHaveBeenCalled();
|
||||
);
|
||||
|
||||
// Act
|
||||
service.logoffAndRevokeTokens(config, [config]).subscribe({
|
||||
error: (err) => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
try {
|
||||
await lastValueFrom(service.logoffAndRevokeTokens(config, [config]));
|
||||
} catch (err: any) {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -141,18 +141,7 @@ export class LogoffRevocationService {
|
||||
return this.revokeRefreshToken(config).pipe(
|
||||
switchMap((_) => this.revokeAccessToken(config)),
|
||||
catchError((error) => {
|
||||
const errorMessage = `revoke token failed`;
|
||||
|
||||
this.loggerService.logError(config, errorMessage, error);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}),
|
||||
concatMap(() => this.logoff(config, allConfigs, logoutAuthOptions))
|
||||
);
|
||||
} else {
|
||||
return this.revokeAccessToken(config).pipe(
|
||||
catchError((error) => {
|
||||
const errorMessage = `revoke accessToken failed`;
|
||||
const errorMessage = 'revoke token failed';
|
||||
|
||||
this.loggerService.logError(config, errorMessage, error);
|
||||
|
||||
@ -161,6 +150,16 @@ export class LogoffRevocationService {
|
||||
concatMap(() => this.logoff(config, allConfigs, logoutAuthOptions))
|
||||
);
|
||||
}
|
||||
return this.revokeAccessToken(config).pipe(
|
||||
catchError((error) => {
|
||||
const errorMessage = 'revoke accessToken failed';
|
||||
|
||||
this.loggerService.logError(config, errorMessage, error);
|
||||
|
||||
return throwError(() => new Error(errorMessage));
|
||||
}),
|
||||
concatMap(() => this.logoff(config, allConfigs, logoutAuthOptions))
|
||||
);
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc7009
|
||||
@ -281,7 +280,7 @@ export class LogoffRevocationService {
|
||||
return of(response);
|
||||
}),
|
||||
catchError((error) => {
|
||||
const errorMessage = `Revocation request failed`;
|
||||
const errorMessage = 'Revocation request failed';
|
||||
|
||||
this.loggerService.logError(configuration, errorMessage, error);
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// biome-ignore lint/nursery/noEnum: <explanation>
|
||||
export enum EventTypes {
|
||||
/**
|
||||
* This only works in the AppModule Constructor
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { EventTypes } from './event-types';
|
||||
import type { EventTypes } from './event-types';
|
||||
|
||||
export interface OidcClientNotification<T> {
|
||||
type: EventTypes;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { vi } from 'vitest';
|
||||
import { EventTypes } from './event-types';
|
||||
@ -11,9 +12,6 @@ describe('Events Service', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [PublicEventsService],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
eventsService = TestBed.inject(PublicEventsService);
|
||||
});
|
||||
|
||||
@ -23,20 +21,20 @@ describe('Events Service', () => {
|
||||
|
||||
it('registering to single event with one event emit works', async () => {
|
||||
const firedEvent = await lastValueFrom(eventsService.registerForEvents());
|
||||
expect(firedEvent).toBeTruthy();;
|
||||
expect(firedEvent).toEqual({
|
||||
type: EventTypes.ConfigLoaded,
|
||||
value: { myKey: 'myValue' },
|
||||
});
|
||||
expect(firedEvent).toBeTruthy();
|
||||
expect(firedEvent).toEqual({
|
||||
type: EventTypes.ConfigLoaded,
|
||||
value: { myKey: 'myValue' },
|
||||
});
|
||||
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
|
||||
});
|
||||
|
||||
it('registering to single event with multiple same event emit works', async () => {
|
||||
const spy = jasmine.createSpy('spy');
|
||||
const spy = vi.fn()('spy');
|
||||
|
||||
const firedEvent = await lastValueFrom(eventsService.registerForEvents());
|
||||
spy(firedEvent);;
|
||||
expect(firedEvent).toBeTruthy();
|
||||
spy(firedEvent);
|
||||
expect(firedEvent).toBeTruthy();
|
||||
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
|
||||
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue2' });
|
||||
|
||||
@ -45,21 +43,23 @@ expect(firedEvent).toBeTruthy();
|
||||
type: EventTypes.ConfigLoaded,
|
||||
value: { myKey: 'myValue' },
|
||||
});
|
||||
expect(spy.calls.mostRecent().args[0]).toEqual({
|
||||
expect(spy.postSpy.mock.calls.at(-1)?.[0]).toEqual({
|
||||
type: EventTypes.ConfigLoaded,
|
||||
value: { myKey: 'myValue2' },
|
||||
});
|
||||
});
|
||||
|
||||
it('registering to single event with multiple emit works', async () => {
|
||||
const firedEvent = await lastValueFrom(eventsService
|
||||
.registerForEvents()
|
||||
.pipe(filter((x) => x.type === EventTypes.ConfigLoaded)));
|
||||
expect(firedEvent).toBeTruthy();;
|
||||
expect(firedEvent).toEqual({
|
||||
type: EventTypes.ConfigLoaded,
|
||||
value: { myKey: 'myValue' },
|
||||
});
|
||||
const firedEvent = await lastValueFrom(
|
||||
eventsService
|
||||
.registerForEvents()
|
||||
.pipe(filter((x) => x.type === EventTypes.ConfigLoaded))
|
||||
);
|
||||
expect(firedEvent).toBeTruthy();
|
||||
expect(firedEvent).toEqual({
|
||||
type: EventTypes.ConfigLoaded,
|
||||
value: { myKey: 'myValue' },
|
||||
});
|
||||
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
|
||||
eventsService.fireEvent(EventTypes.NewAuthenticationResult, true);
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { Observable, ReplaySubject } from 'rxjs';
|
||||
import { EventTypes } from './event-types';
|
||||
import { OidcClientNotification } from './notification';
|
||||
import { type Observable, ReplaySubject } from 'rxjs';
|
||||
import type { EventTypes } from './event-types';
|
||||
import type { OidcClientNotification } from './notification';
|
||||
|
||||
@Injectable()
|
||||
export class PublicEventsService {
|
||||
|
@ -11,7 +11,7 @@ export interface RouterStateSnapshot {
|
||||
}
|
||||
|
||||
export abstract class AbstractRouter {
|
||||
navigateByUrl(url: string): void {
|
||||
navigateByUrl(_url: string): void {
|
||||
// TODO
|
||||
// Implementation of navigating to a URL
|
||||
}
|
||||
@ -23,5 +23,9 @@ export abstract class AbstractRouter {
|
||||
}
|
||||
|
||||
// TODO
|
||||
parseUrl(url: string) {}
|
||||
parseUrl(_url: string): any {
|
||||
// TODO
|
||||
// Implementation of getting the current navigation
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,6 @@ describe('BrowserStorageService', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
abstractSecurityStorage = TestBed.inject(AbstractSecurityStorage);
|
||||
service = TestBed.inject(BrowserStorageService);
|
||||
});
|
||||
@ -76,7 +73,7 @@ describe('BrowserStorageService', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
const writeSpy = vi.spyOn(abstractSecurityStorage, 'write')();
|
||||
const writeSpy = vi.spyOn(abstractSecurityStorage, 'write');
|
||||
|
||||
const result = service.write({ anyKey: 'anyvalue' }, config);
|
||||
|
||||
@ -92,7 +89,7 @@ describe('BrowserStorageService', () => {
|
||||
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
|
||||
const writeSpy = vi.spyOn(abstractSecurityStorage, 'write')();
|
||||
const writeSpy = vi.spyOn(abstractSecurityStorage, 'write');
|
||||
const somethingFalsy = '';
|
||||
|
||||
const result = service.write(somethingFalsy, config);
|
||||
@ -117,7 +114,7 @@ describe('BrowserStorageService', () => {
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
const setItemSpy = vi.spyOn(abstractSecurityStorage, 'remove')();
|
||||
const setItemSpy = vi.spyOn(abstractSecurityStorage, 'remove');
|
||||
|
||||
const result = service.remove('anyKey', config);
|
||||
|
||||
@ -137,7 +134,7 @@ describe('BrowserStorageService', () => {
|
||||
it('returns true if clear is called', () => {
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
|
||||
const setItemSpy = vi.spyOn(abstractSecurityStorage, 'clear')();
|
||||
const setItemSpy = vi.spyOn(abstractSecurityStorage, 'clear');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
const result = service.clear(config);
|
||||
@ -149,8 +146,11 @@ describe('BrowserStorageService', () => {
|
||||
|
||||
describe('hasStorage', () => {
|
||||
it('returns false if there is no storage', () => {
|
||||
// biome-ignore lint/suspicious/noGlobalAssign: <explanation>
|
||||
(Storage as any) = undefined;
|
||||
expect((service as any).hasStorage()).toBeFalsy();
|
||||
// biome-ignore lint/correctness/noSelfAssign: <explanation>
|
||||
// biome-ignore lint/suspicious/noGlobalAssign: <explanation>
|
||||
Storage = Storage;
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { AbstractSecurityStorage } from './abstract-security-storage';
|
||||
|
||||
@ -54,7 +54,7 @@ export class BrowserStorageService {
|
||||
if (!this.hasStorage()) {
|
||||
this.loggerService.logDebug(
|
||||
configuration,
|
||||
`Wanted to write but Storage was falsy`
|
||||
'Wanted to write but Storage was falsy'
|
||||
);
|
||||
|
||||
return false;
|
||||
@ -94,7 +94,7 @@ export class BrowserStorageService {
|
||||
if (!this.hasStorage()) {
|
||||
this.loggerService.logDebug(
|
||||
configuration,
|
||||
`Wanted to clear storage but Storage was falsy`
|
||||
'Wanted to clear storage but Storage was falsy'
|
||||
);
|
||||
|
||||
return false;
|
||||
|
@ -9,9 +9,6 @@ describe('DefaultLocalStorageService', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [DefaultLocalStorageService],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(DefaultLocalStorageService);
|
||||
});
|
||||
|
||||
|
@ -1,21 +1,21 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { AbstractSecurityStorage } from './abstract-security-storage';
|
||||
import type { AbstractSecurityStorage } from './abstract-security-storage';
|
||||
|
||||
@Injectable()
|
||||
export class DefaultLocalStorageService implements AbstractSecurityStorage {
|
||||
public read(key: string): string | null {
|
||||
read(key: string): string | null {
|
||||
return localStorage.getItem(key);
|
||||
}
|
||||
|
||||
public write(key: string, value: string): void {
|
||||
write(key: string, value: string): void {
|
||||
localStorage.setItem(key, value);
|
||||
}
|
||||
|
||||
public remove(key: string): void {
|
||||
remove(key: string): void {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
clear(): void {
|
||||
localStorage.clear();
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,6 @@ describe('DefaultSessionStorageService', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [DefaultSessionStorageService],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(DefaultSessionStorageService);
|
||||
});
|
||||
|
||||
|
@ -1,21 +1,21 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { AbstractSecurityStorage } from './abstract-security-storage';
|
||||
import type { AbstractSecurityStorage } from './abstract-security-storage';
|
||||
|
||||
@Injectable()
|
||||
export class DefaultSessionStorageService implements AbstractSecurityStorage {
|
||||
public read(key: string): string | null {
|
||||
read(key: string): string | null {
|
||||
return sessionStorage.getItem(key);
|
||||
}
|
||||
|
||||
public write(key: string, value: string): void {
|
||||
write(key: string, value: string): void {
|
||||
sessionStorage.setItem(key, value);
|
||||
}
|
||||
|
||||
public remove(key: string): void {
|
||||
remove(key: string): void {
|
||||
sessionStorage.removeItem(key);
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
clear(): void {
|
||||
sessionStorage.clear();
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,6 @@ describe('Storage Persistence Service', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [mockProvider(BrowserStorageService)],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(StoragePersistenceService);
|
||||
securityStorage = TestBed.inject(BrowserStorageService);
|
||||
});
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { type Observable, of } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { vi } from 'vitest';
|
||||
|
||||
// Create retriable observable stream to test retry / retryWhen. Credits to:
|
||||
// https://stackoverflow.com/questions/51399819/how-to-create-a-mock-observable-to-test-http-rxjs-retry-retrywhen-in-angular
|
||||
export const createRetriableStream = (...resp$: any): Observable<any> => {
|
||||
const fetchData: jasmine.Spy = jasmine.createSpy('fetchData');
|
||||
const fetchData = vi.fn()('fetchData');
|
||||
|
||||
fetchData.mockReturnValues(...resp$);
|
||||
|
||||
|
@ -50,7 +50,7 @@ describe('User Service', () => {
|
||||
expect(userService).toBeTruthy();
|
||||
});
|
||||
|
||||
it('public authorize$ is observable$', () => {
|
||||
it('authorize$ is observable$', () => {
|
||||
expect(userService.userData$).toBeInstanceOf(Observable);
|
||||
});
|
||||
|
||||
@ -225,6 +225,7 @@ describe('User Service', () => {
|
||||
const idToken = '';
|
||||
const decodedIdToken = { sub: 'decodedIdToken' };
|
||||
const userDataInstore = '';
|
||||
// biome-ignore lint/suspicious/noEvolvingTypes: <explanation>
|
||||
const userDataFromSts = null;
|
||||
|
||||
const config = {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { CryptoService } from './crypto.service';
|
||||
|
||||
@ -16,9 +15,6 @@ describe('CryptoService', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cryptoService = TestBed.inject(CryptoService);
|
||||
});
|
||||
|
||||
@ -50,9 +46,6 @@ describe('CryptoService: msCrypto', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cryptoService = TestBed.inject(CryptoService);
|
||||
});
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { IFrameService } from '../../iframe/existing-iframe.service';
|
||||
import { EqualityService } from './equality.service';
|
||||
|
||||
@ -10,9 +9,6 @@ describe('EqualityService Tests', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [EqualityService, IFrameService],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
equalityHelperService = TestBed.inject(EqualityService);
|
||||
});
|
||||
|
||||
|
@ -99,7 +99,7 @@ export class EqualityService {
|
||||
return typeof value === 'object';
|
||||
}
|
||||
|
||||
private arraysStrictEqual(arr1: Array<string>, arr2: Array<string>): boolean {
|
||||
private arraysStrictEqual(arr1: string[], arr2: string[]): boolean {
|
||||
if (arr1.length !== arr2.length) {
|
||||
return false;
|
||||
}
|
||||
@ -113,10 +113,7 @@ export class EqualityService {
|
||||
return true;
|
||||
}
|
||||
|
||||
private arraysHaveEqualContent(
|
||||
arr1: Array<string>,
|
||||
arr2: Array<string>
|
||||
): boolean {
|
||||
private arraysHaveEqualContent(arr1: string[], arr2: string[]): boolean {
|
||||
if (arr1.length !== arr2.length) {
|
||||
return false;
|
||||
}
|
||||
|
@ -9,9 +9,6 @@ describe('Flow Helper Service', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [FlowHelper],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
flowHelper = TestBed.inject(FlowHelper);
|
||||
});
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user