fix: fix observable

This commit is contained in:
master 2025-01-31 03:23:45 +08:00
parent 733b697ee2
commit 316361bd3c
45 changed files with 1084 additions and 1355 deletions

View File

@ -9,6 +9,9 @@
"suspicious": { "suspicious": {
"noExplicitAny": "off" "noExplicitAny": "off"
}, },
"complexity": {
"noForEach": "info"
},
"correctness": { "correctness": {
"noUnusedImports": { "noUnusedImports": {
"fix": "none", "fix": "none",

View File

@ -51,6 +51,7 @@
"@playwright/test": "^1.49.1", "@playwright/test": "^1.49.1",
"@rslib/core": "^0.3.1", "@rslib/core": "^0.3.1",
"@types/lodash-es": "^4.17.12", "@types/lodash-es": "^4.17.12",
"@types/node": "^22.12.0",
"@vitest/coverage-v8": "^3.0.1", "@vitest/coverage-v8": "^3.0.1",
"commander": "^13.1.0", "commander": "^13.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",

43
pnpm-lock.yaml generated
View File

@ -39,9 +39,12 @@ importers:
'@types/lodash-es': '@types/lodash-es':
specifier: ^4.17.12 specifier: ^4.17.12
version: 4.17.12 version: 4.17.12
'@types/node':
specifier: ^22.12.0
version: 22.12.0
'@vitest/coverage-v8': '@vitest/coverage-v8':
specifier: ^3.0.1 specifier: ^3.0.1
version: 3.0.1(vitest@3.0.1(@types/node@22.10.7)(tsx@4.19.2)) version: 3.0.1(vitest@3.0.1(@types/node@22.12.0)(tsx@4.19.2))
commander: commander:
specifier: ^13.1.0 specifier: ^13.1.0
version: 13.1.0 version: 13.1.0
@ -71,7 +74,7 @@ importers:
version: 4.1.15 version: 4.1.15
vitest: vitest:
specifier: ^3.0.1 specifier: ^3.0.1
version: 3.0.1(@types/node@22.10.7)(tsx@4.19.2) version: 3.0.1(@types/node@22.12.0)(tsx@4.19.2)
packages: packages:
@ -756,8 +759,8 @@ packages:
'@types/lodash@4.17.15': '@types/lodash@4.17.15':
resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==} resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==}
'@types/node@22.10.7': '@types/node@22.12.0':
resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==} resolution: {integrity: sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==}
'@vitest/coverage-v8@3.0.1': '@vitest/coverage-v8@3.0.1':
resolution: {integrity: sha512-WpbI1QtkWpzMQTP5S3IneIWN714bOPcPFYp9Q9tXK9YgAtmMsrzKut0mFwSAu31CmbY0Q6Xsp15biO7Tjwp7UQ==} resolution: {integrity: sha512-WpbI1QtkWpzMQTP5S3IneIWN714bOPcPFYp9Q9tXK9YgAtmMsrzKut0mFwSAu31CmbY0Q6Xsp15biO7Tjwp7UQ==}
@ -1741,12 +1744,11 @@ snapshots:
'@types/lodash@4.17.15': {} '@types/lodash@4.17.15': {}
'@types/node@22.10.7': '@types/node@22.12.0':
dependencies: dependencies:
undici-types: 6.20.0 undici-types: 6.20.0
optional: true
'@vitest/coverage-v8@3.0.1(vitest@3.0.1(@types/node@22.10.7)(tsx@4.19.2))': '@vitest/coverage-v8@3.0.1(vitest@3.0.1(@types/node@22.12.0)(tsx@4.19.2))':
dependencies: dependencies:
'@ampproject/remapping': 2.3.0 '@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 1.0.2 '@bcoe/v8-coverage': 1.0.2
@ -1760,7 +1762,7 @@ snapshots:
std-env: 3.8.0 std-env: 3.8.0
test-exclude: 7.0.1 test-exclude: 7.0.1
tinyrainbow: 2.0.0 tinyrainbow: 2.0.0
vitest: 3.0.1(@types/node@22.10.7)(tsx@4.19.2) vitest: 3.0.1(@types/node@22.12.0)(tsx@4.19.2)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -1771,13 +1773,13 @@ snapshots:
chai: 5.1.2 chai: 5.1.2
tinyrainbow: 2.0.0 tinyrainbow: 2.0.0
'@vitest/mocker@3.0.1(vite@6.0.7(@types/node@22.10.7)(tsx@4.19.2))': '@vitest/mocker@3.0.1(vite@6.0.7(@types/node@22.12.0)(tsx@4.19.2))':
dependencies: dependencies:
'@vitest/spy': 3.0.1 '@vitest/spy': 3.0.1
estree-walker: 3.0.3 estree-walker: 3.0.3
magic-string: 0.30.17 magic-string: 0.30.17
optionalDependencies: optionalDependencies:
vite: 6.0.7(@types/node@22.10.7)(tsx@4.19.2) vite: 6.0.7(@types/node@22.12.0)(tsx@4.19.2)
'@vitest/pretty-format@3.0.1': '@vitest/pretty-format@3.0.1':
dependencies: dependencies:
@ -2233,21 +2235,20 @@ snapshots:
dependencies: dependencies:
commander: 12.1.0 commander: 12.1.0
undici-types@6.20.0: undici-types@6.20.0: {}
optional: true
unplugin@1.16.1: unplugin@1.16.1:
dependencies: dependencies:
acorn: 8.14.0 acorn: 8.14.0
webpack-virtual-modules: 0.6.2 webpack-virtual-modules: 0.6.2
vite-node@3.0.1(@types/node@22.10.7)(tsx@4.19.2): vite-node@3.0.1(@types/node@22.12.0)(tsx@4.19.2):
dependencies: dependencies:
cac: 6.7.14 cac: 6.7.14
debug: 4.4.0 debug: 4.4.0
es-module-lexer: 1.6.0 es-module-lexer: 1.6.0
pathe: 2.0.1 pathe: 2.0.1
vite: 6.0.7(@types/node@22.10.7)(tsx@4.19.2) vite: 6.0.7(@types/node@22.12.0)(tsx@4.19.2)
transitivePeerDependencies: transitivePeerDependencies:
- '@types/node' - '@types/node'
- jiti - jiti
@ -2262,20 +2263,20 @@ snapshots:
- tsx - tsx
- yaml - yaml
vite@6.0.7(@types/node@22.10.7)(tsx@4.19.2): vite@6.0.7(@types/node@22.12.0)(tsx@4.19.2):
dependencies: dependencies:
esbuild: 0.24.2 esbuild: 0.24.2
postcss: 8.5.1 postcss: 8.5.1
rollup: 4.30.1 rollup: 4.30.1
optionalDependencies: optionalDependencies:
'@types/node': 22.10.7 '@types/node': 22.12.0
fsevents: 2.3.3 fsevents: 2.3.3
tsx: 4.19.2 tsx: 4.19.2
vitest@3.0.1(@types/node@22.10.7)(tsx@4.19.2): vitest@3.0.1(@types/node@22.12.0)(tsx@4.19.2):
dependencies: dependencies:
'@vitest/expect': 3.0.1 '@vitest/expect': 3.0.1
'@vitest/mocker': 3.0.1(vite@6.0.7(@types/node@22.10.7)(tsx@4.19.2)) '@vitest/mocker': 3.0.1(vite@6.0.7(@types/node@22.12.0)(tsx@4.19.2))
'@vitest/pretty-format': 3.0.1 '@vitest/pretty-format': 3.0.1
'@vitest/runner': 3.0.1 '@vitest/runner': 3.0.1
'@vitest/snapshot': 3.0.1 '@vitest/snapshot': 3.0.1
@ -2291,11 +2292,11 @@ snapshots:
tinyexec: 0.3.2 tinyexec: 0.3.2
tinypool: 1.0.2 tinypool: 1.0.2
tinyrainbow: 2.0.0 tinyrainbow: 2.0.0
vite: 6.0.7(@types/node@22.10.7)(tsx@4.19.2) vite: 6.0.7(@types/node@22.12.0)(tsx@4.19.2)
vite-node: 3.0.1(@types/node@22.10.7)(tsx@4.19.2) vite-node: 3.0.1(@types/node@22.12.0)(tsx@4.19.2)
why-is-node-running: 2.3.0 why-is-node-running: 2.3.0
optionalDependencies: optionalDependencies:
'@types/node': 22.10.7 '@types/node': 22.12.0
transitivePeerDependencies: transitivePeerDependencies:
- jiti - jiti
- less - less

View File

@ -1,11 +1,6 @@
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import fsp from 'node:fs/promises'; import fsp from 'node:fs/promises';
import { import { type MagicString, type Statement, parseSync } from 'oxc-parser';
type ClassElement,
type MagicString,
type Statement,
parseSync,
} from 'oxc-parser';
import { type Node, walk } from 'oxc-walker'; import { type Node, walk } from 'oxc-walker';
function sourceTextFromNode( function sourceTextFromNode(
@ -35,6 +30,22 @@ export async function rewriteObservableSubscribeToLastValueFrom(
const newChildren: T = [] as any as T; const newChildren: T = [] as any as T;
for (const child of children) { for (const child of children) {
if ( if (
child.type === 'ExpressionStatement' &&
child.expression.type === 'CallExpression' &&
child.expression.callee.type === 'StaticMemberExpression' &&
child.expression.callee.property.name === 'subscribe' &&
child.expression.arguments.length === 0
) {
const newContent = `await lastValueFrom(${sourceTextFromNode(context, child.expression.callee.object)});`;
const newStatements = parseSync('index.ts', newContent).program
.body as any[];
magicString.remove(child.start, child.end);
magicString.appendRight(child.start, newContent);
newChildren.push(...newStatements);
} else if (
child.type === 'ExpressionStatement' && child.type === 'ExpressionStatement' &&
child.expression.type === 'CallExpression' && child.expression.type === 'CallExpression' &&
child.expression.callee.type === 'StaticMemberExpression' && child.expression.callee.type === 'StaticMemberExpression' &&
@ -72,7 +83,6 @@ export async function rewriteObservableSubscribeToLastValueFrom(
} else { } else {
newChildren.push(child as any); newChildren.push(child as any);
} }
return newChildren;
} }
return newChildren; return newChildren;
}; };
@ -85,7 +95,6 @@ export async function rewriteObservableSubscribeToLastValueFrom(
'type' in node.body && 'type' in node.body &&
node.body.type === 'FunctionBody' node.body.type === 'FunctionBody'
) { ) {
console.error('xxx', node.body.type);
const children = node.body.statements; const children = node.body.statements;
node.body.statements = transformExprs(children)!; node.body.statements = transformExprs(children)!;
} }
@ -102,11 +111,7 @@ export async function rewriteAllObservableSubscribeToLastValueFrom(
) { ) {
const files = fsp.glob(pattern); const files = fsp.glob(pattern);
for await (const file of files) { for await (const file of files) {
const source = await fsp.readFile(file, 'utf-8');
const result = await rewriteObservableSubscribeToLastValueFrom(file); const result = await rewriteObservableSubscribeToLastValueFrom(file);
if (source !== result) {
console.error('not equal');
}
await fsp.writeFile(file, result, 'utf-8'); await fsp.writeFile(file, result, 'utf-8');
} }

View File

@ -1,15 +1,9 @@
import { TestBed } from '@/testing/testbed'; import { TestBed } from '@/testing';
import { import { provideHttpClientTesting } from '@/testing/http';
HttpHeaders, import { HttpHeaders } from '@ngify/http';
provideHttpClient, import { HttpTestingController } from '@ngify/http/testing';
withInterceptorsFromDi, import { provideHttpClient, withInterceptorsFromDi } from 'oidc-client-rx';
} from '@ngify/http';
import {
HttpTestingController,
provideHttpClientTesting,
} from '@ngify/http/testing';
import { lastValueFrom } from 'rxjs'; import { lastValueFrom } from 'rxjs';
import { vi } from 'vitest';
import { DataService } from './data.service'; import { DataService } from './data.service';
import { HttpBaseService } from './http-base.service'; import { HttpBaseService } from './http-base.service';
@ -39,11 +33,10 @@ describe('Data Service', () => {
it('get call sets the accept header', async () => { it('get call sets the accept header', async () => {
const url = 'testurl'; const url = 'testurl';
dataService const data = await lastValueFrom(
.get(url, { configId: 'configId1' }) dataService.get(url, { configId: 'configId1' })
.subscribe((data: unknown) => { );
expect(data).toBe('bodyData'); expect(data).toBe('bodyData');
});
const req = httpMock.expectOne(url); const req = httpMock.expectOne(url);
expect(req.request.method).toBe('GET'); expect(req.request.method).toBe('GET');
@ -58,11 +51,10 @@ describe('Data Service', () => {
const url = 'testurl'; const url = 'testurl';
const token = 'token'; const token = 'token';
dataService const data = await lastValueFrom(
.get(url, { configId: 'configId1' }, token) dataService.get(url, { configId: 'configId1' }, token)
.subscribe((data: unknown) => { );
expect(data).toBe('bodyData'); expect(data).toBe('bodyData');
});
const req = httpMock.expectOne(url); const req = httpMock.expectOne(url);
expect(req.request.method).toBe('GET'); expect(req.request.method).toBe('GET');
@ -77,11 +69,10 @@ describe('Data Service', () => {
it('call without ngsw-bypass param by default', async () => { it('call without ngsw-bypass param by default', async () => {
const url = 'testurl'; const url = 'testurl';
dataService const data = await lastValueFrom(
.get(url, { configId: 'configId1' }) dataService.get(url, { configId: 'configId1' })
.subscribe((data: unknown) => { );
expect(data).toBe('bodyData'); expect(data).toBe('bodyData');
});
const req = httpMock.expectOne(url); const req = httpMock.expectOne(url);
expect(req.request.method).toBe('GET'); expect(req.request.method).toBe('GET');
@ -96,11 +87,10 @@ describe('Data Service', () => {
it('call with ngsw-bypass param', async () => { it('call with ngsw-bypass param', async () => {
const url = 'testurl'; const url = 'testurl';
dataService const data = await lastValueFrom(
.get(url, { configId: 'configId1', ngswBypass: true }) dataService.get(url, { configId: 'configId1', ngswBypass: true })
.subscribe((data: unknown) => { );
expect(data).toBe('bodyData'); expect(data).toBe('bodyData');
});
const req = httpMock.expectOne(`${url}?ngsw-bypass=`); const req = httpMock.expectOne(`${url}?ngsw-bypass=`);
expect(req.request.method).toBe('GET'); expect(req.request.method).toBe('GET');
@ -117,9 +107,8 @@ describe('Data Service', () => {
it('call sets the accept header when no other params given', async () => { it('call sets the accept header when no other params given', async () => {
const url = 'testurl'; const url = 'testurl';
dataService await lastValueFrom(dataService
.post(url, { some: 'thing' }, { configId: 'configId1' }) .post(url, { some: 'thing' }, { configId: 'configId1' }));
.subscribe();
const req = httpMock.expectOne(url); const req = httpMock.expectOne(url);
expect(req.request.method).toBe('POST'); expect(req.request.method).toBe('POST');

View File

@ -153,14 +153,13 @@ describe('CheckAuthService', () => {
]; ];
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig'); const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1', authority: 'some-authority' }, { configId: 'configId1', authority: 'some-authority' },
allConfigs, allConfigs,
undefined undefined
); );
}); });
});
it('returns null and sendMessageToMainWindow if currently in a popup', async () => { it('returns null and sendMessageToMainWindow if currently in a popup', async () => {
const allConfigs = [ const allConfigs = [
@ -181,9 +180,8 @@ describe('CheckAuthService', () => {
vi.spyOn(popUpService, 'isCurrentlyInPopup').mockReturnValue(true); vi.spyOn(popUpService, 'isCurrentlyInPopup').mockReturnValue(true);
const popupSpy = vi.spyOn(popUpService, 'sendMessageToMainWindow'); const popupSpy = vi.spyOn(popUpService, 'sendMessageToMainWindow');
checkAuthService const result = await lastValueFrom(checkAuthService
.checkAuth(allConfigs[0]!, allConfigs) .checkAuth(allConfigs[0]!, allConfigs));
.subscribe((result) => {
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: false, isAuthenticated: false,
errorMessage: '', errorMessage: '',
@ -191,10 +189,9 @@ describe('CheckAuthService', () => {
idToken: '', idToken: '',
accessToken: '', accessToken: '',
configId: '', configId: '',
}); });;
expect(popupSpy).toHaveBeenCalled(); expect(popupSpy).toHaveBeenCalled();
}); });
});
it('returns isAuthenticated: false with error message in case handleCallbackAndFireEvents throws an error', async () => { it('returns isAuthenticated: false with error message in case handleCallbackAndFireEvents throws an error', async () => {
const allConfigs = [ const allConfigs = [
@ -214,9 +211,8 @@ describe('CheckAuthService', () => {
'http://localhost:4200' 'http://localhost:4200'
); );
checkAuthService const result = await lastValueFrom(checkAuthService
.checkAuth(allConfigs[0]!, allConfigs) .checkAuth(allConfigs[0]!, allConfigs));
.subscribe((result) => {
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: false, isAuthenticated: false,
errorMessage: 'ERROR', errorMessage: 'ERROR',
@ -224,10 +220,9 @@ describe('CheckAuthService', () => {
idToken: '', idToken: '',
userData: null, userData: null,
accessToken: '', accessToken: '',
}); });;
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('calls callbackService.handlePossibleStsCallback with current url when callback is true', async () => { it('calls callbackService.handlePossibleStsCallback with current url when callback is true', async () => {
const allConfigs = [ const allConfigs = [
@ -248,19 +243,17 @@ describe('CheckAuthService', () => {
.spyOn(callBackService, 'handleCallbackAndFireEvents') .spyOn(callBackService, 'handleCallbackAndFireEvents')
.mockReturnValue(of({} as CallbackContext)); .mockReturnValue(of({} as CallbackContext));
checkAuthService const result = await lastValueFrom(checkAuthService
.checkAuth(allConfigs[0]!, allConfigs) .checkAuth(allConfigs[0]!, allConfigs));
.subscribe((result) => {
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: true, isAuthenticated: true,
userData: undefined, userData: undefined,
accessToken: 'at', accessToken: 'at',
configId: 'configId1', configId: 'configId1',
idToken: 'idt', idToken: 'idt',
}); });;
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('does NOT call handleCallbackAndFireEvents with current url when callback is false', async () => { it('does NOT call handleCallbackAndFireEvents with current url when callback is false', async () => {
const allConfigs = [ const allConfigs = [
@ -282,19 +275,17 @@ describe('CheckAuthService', () => {
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('at'); vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('at');
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idt'); vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idt');
checkAuthService const result = await lastValueFrom(checkAuthService
.checkAuth(allConfigs[0]!, allConfigs) .checkAuth(allConfigs[0]!, allConfigs));
.subscribe((result) => {
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: true, isAuthenticated: true,
userData: undefined, userData: undefined,
accessToken: 'at', accessToken: 'at',
configId: 'configId1', configId: 'configId1',
idToken: 'idt', idToken: 'idt',
}); });;
expect(spy).not.toHaveBeenCalled(); 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 () => { it('does fire the auth and user data events when it is not a callback from the security token service and is authenticated', async () => {
const allConfigs = [ const allConfigs = [
@ -323,9 +314,8 @@ describe('CheckAuthService', () => {
); );
const userServiceSpy = vi.spyOn(userService, 'publishUserDataIfExists'); const userServiceSpy = vi.spyOn(userService, 'publishUserDataIfExists');
checkAuthService const result = await lastValueFrom(checkAuthService
.checkAuth(allConfigs[0]!, allConfigs) .checkAuth(allConfigs[0]!, allConfigs));
.subscribe((result) => {
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: true, isAuthenticated: true,
userData: { userData: {
@ -334,11 +324,10 @@ describe('CheckAuthService', () => {
accessToken: 'at', accessToken: 'at',
configId: 'configId1', configId: 'configId1',
idToken: 'idt', idToken: 'idt',
}); });;
expect(setAuthorizedAndFireEventSpy).toHaveBeenCalled(); expect(setAuthorizedAndFireEventSpy).toHaveBeenCalled();;
expect(userServiceSpy).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 () => { 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 () => {
const allConfigs = [ const allConfigs = [
@ -364,20 +353,18 @@ describe('CheckAuthService', () => {
); );
const userServiceSpy = vi.spyOn(userService, 'publishUserDataIfExists'); const userServiceSpy = vi.spyOn(userService, 'publishUserDataIfExists');
checkAuthService const result = await lastValueFrom(checkAuthService
.checkAuth(allConfigs[0]!, allConfigs) .checkAuth(allConfigs[0]!, allConfigs));
.subscribe((result) => {
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: false, isAuthenticated: false,
userData: undefined, userData: undefined,
accessToken: 'at', accessToken: 'at',
configId: 'configId1', configId: 'configId1',
idToken: 'it', idToken: 'it',
}); });;
expect(setAuthorizedAndFireEventSpy).not.toHaveBeenCalled(); expect(setAuthorizedAndFireEventSpy).not.toHaveBeenCalled();;
expect(userServiceSpy).not.toHaveBeenCalled(); expect(userServiceSpy).not.toHaveBeenCalled();
}); });
});
it('if authenticated return true', async () => { it('if authenticated return true', async () => {
const allConfigs = [ const allConfigs = [
@ -396,9 +383,8 @@ describe('CheckAuthService', () => {
true true
); );
checkAuthService const result = await lastValueFrom(checkAuthService
.checkAuth(allConfigs[0]!, allConfigs) .checkAuth(allConfigs[0]!, allConfigs));
.subscribe((result) => {
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: true, isAuthenticated: true,
userData: undefined, userData: undefined,
@ -407,7 +393,6 @@ describe('CheckAuthService', () => {
idToken: 'idt', idToken: 'idt',
}); });
}); });
});
it('if authenticated set auth and fires event ', async () => { it('if authenticated set auth and fires event ', async () => {
const allConfigs = [ const allConfigs = [
@ -424,10 +409,9 @@ describe('CheckAuthService', () => {
const spy = vi.spyOn(authStateService, 'setAuthenticatedAndFireEvent'); const spy = vi.spyOn(authStateService, 'setAuthenticatedAndFireEvent');
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('if authenticated publishUserdataIfExists', async () => { it('if authenticated publishUserdataIfExists', async () => {
const allConfigs = [ const allConfigs = [
@ -446,10 +430,9 @@ describe('CheckAuthService', () => {
const spy = vi.spyOn(userService, 'publishUserDataIfExists'); const spy = vi.spyOn(userService, 'publishUserDataIfExists');
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('if authenticated callbackService startTokenValidationPeriodically', async () => { it('if authenticated callbackService startTokenValidationPeriodically', async () => {
const config = { const config = {
@ -472,10 +455,9 @@ describe('CheckAuthService', () => {
'startTokenValidationPeriodically' 'startTokenValidationPeriodically'
); );
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('if isCheckSessionConfigured call checkSessionService.start()', async () => { it('if isCheckSessionConfigured call checkSessionService.start()', async () => {
const allConfigs = [ const allConfigs = [
@ -496,10 +478,9 @@ describe('CheckAuthService', () => {
); );
const spy = vi.spyOn(checkSessionService, 'start'); const spy = vi.spyOn(checkSessionService, 'start');
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('if isSilentRenewConfigured call getOrCreateIframe()', async () => { it('if isSilentRenewConfigured call getOrCreateIframe()', async () => {
const allConfigs = [ const allConfigs = [
@ -520,10 +501,9 @@ describe('CheckAuthService', () => {
); );
const spy = vi.spyOn(silentRenewService, 'getOrCreateIframe'); const spy = vi.spyOn(silentRenewService, 'getOrCreateIframe');
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('calls checkSavedRedirectRouteAndNavigate if authenticated', async () => { it('calls checkSavedRedirectRouteAndNavigate if authenticated', async () => {
const allConfigs = [ const allConfigs = [
@ -544,11 +524,10 @@ describe('CheckAuthService', () => {
'checkSavedRedirectRouteAndNavigate' 'checkSavedRedirectRouteAndNavigate'
); );
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledTimes(1);;
expect(spy).toHaveBeenCalledExactlyOnceWith(allConfigs[0]); expect(spy).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
}); });
});
it('does not call checkSavedRedirectRouteAndNavigate if not authenticated', async () => { it('does not call checkSavedRedirectRouteAndNavigate if not authenticated', async () => {
const allConfigs = [ const allConfigs = [
@ -566,10 +545,9 @@ describe('CheckAuthService', () => {
'checkSavedRedirectRouteAndNavigate' 'checkSavedRedirectRouteAndNavigate'
); );
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(spy).toHaveBeenCalledTimes(0); expect(spy).toHaveBeenCalledTimes(0);
}); });
});
it('fires CheckingAuth-Event on start and finished event on end', async () => { it('fires CheckingAuth-Event on start and finished event on end', async () => {
const allConfigs = [ const allConfigs = [
@ -585,13 +563,12 @@ describe('CheckAuthService', () => {
const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent'); const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent');
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(fireEventSpy).toHaveBeenCalledWith([ expect(fireEventSpy).toHaveBeenCalledWith([
[EventTypes.CheckingAuth], [EventTypes.CheckingAuth],
[EventTypes.CheckingAuthFinished], [EventTypes.CheckingAuthFinished],
]); ]);
}); });
});
it('fires CheckingAuth-Event on start and CheckingAuthFinishedWithError event on end if exception occurs', async () => { it('fires CheckingAuth-Event on start and CheckingAuthFinishedWithError event on end if exception occurs', async () => {
const allConfigs = [ const allConfigs = [
@ -607,13 +584,12 @@ describe('CheckAuthService', () => {
'http://localhost:4200' 'http://localhost:4200'
); );
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(fireEventSpy).toHaveBeenCalledWith([ expect(fireEventSpy).toHaveBeenCalledWith([
[EventTypes.CheckingAuth], [EventTypes.CheckingAuth],
[EventTypes.CheckingAuthFinishedWithError, 'ERROR'], [EventTypes.CheckingAuthFinishedWithError, 'ERROR'],
]); ]);
}); });
});
it('fires CheckingAuth-Event on start and finished event on end if not authenticated', async () => { it('fires CheckingAuth-Event on start and finished event on end if not authenticated', async () => {
const allConfigs = [ const allConfigs = [
@ -629,14 +605,13 @@ describe('CheckAuthService', () => {
const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent'); const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent');
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(checkAuthService.checkAuth(allConfigs[0]!, allConfigs));
expect(fireEventSpy).toBeCalledWith([ expect(fireEventSpy).toBeCalledWith([
[EventTypes.CheckingAuth], [EventTypes.CheckingAuth],
[EventTypes.CheckingAuthFinished], [EventTypes.CheckingAuthFinished],
]); ]);
}); });
}); });
});
describe('checkAuthIncludingServer', () => { describe('checkAuthIncludingServer', () => {
it('if isSilentRenewConfigured call getOrCreateIframe()', async () => { it('if isSilentRenewConfigured call getOrCreateIframe()', async () => {
@ -659,12 +634,10 @@ describe('CheckAuthService', () => {
); );
const spy = vi.spyOn(silentRenewService, 'getOrCreateIframe'); const spy = vi.spyOn(silentRenewService, 'getOrCreateIframe');
checkAuthService await lastValueFrom(checkAuthService
.checkAuthIncludingServer(allConfigs[0]!, allConfigs) .checkAuthIncludingServer(allConfigs[0]!, allConfigs));
.subscribe(() => {
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('does forceRefreshSession get called and is NOT authenticated', async () => { it('does forceRefreshSession get called and is NOT authenticated', async () => {
const allConfigs = [ const allConfigs = [
@ -689,12 +662,10 @@ describe('CheckAuthService', () => {
}) })
); );
checkAuthService const result = await lastValueFrom(checkAuthService
.checkAuthIncludingServer(allConfigs[0]!, allConfigs) .checkAuthIncludingServer(allConfigs[0]!, allConfigs));
.subscribe((result) => {
expect(result).toBeTruthy(); expect(result).toBeTruthy();
}); });
});
it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing with silentrenew', async () => { it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing with silentrenew', async () => {
const allConfigs = [ const allConfigs = [
@ -738,18 +709,16 @@ describe('CheckAuthService', () => {
}) })
); );
checkAuthService await lastValueFrom(checkAuthService
.checkAuthIncludingServer(allConfigs[0]!, allConfigs) .checkAuthIncludingServer(allConfigs[0]!, allConfigs));
.subscribe(() => {
expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith( expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith(
allConfigs[0] allConfigs[0]
); );;
expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1); expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1);;
expect(getOrCreateIframeSpy).toHaveBeenCalledExactlyOnceWith( expect(getOrCreateIframeSpy).toHaveBeenCalledExactlyOnceWith(
allConfigs[0] allConfigs[0]
); );
}); });
});
it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing without silentrenew', async () => { it('should start check session and validation after forceRefreshSession has been called and is authenticated after forcing without silentrenew', async () => {
const allConfigs = [ const allConfigs = [
@ -793,17 +762,15 @@ describe('CheckAuthService', () => {
}) })
); );
checkAuthService await lastValueFrom(checkAuthService
.checkAuthIncludingServer(allConfigs[0]!, allConfigs) .checkAuthIncludingServer(allConfigs[0]!, allConfigs));
.subscribe(() => {
expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith( expect(checkSessionServiceStartSpy).toHaveBeenCalledExactlyOnceWith(
allConfigs[0] allConfigs[0]
); );;
expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1); expect(periodicallyTokenCheckServiceSpy).toHaveBeenCalledTimes(1);;
expect(getOrCreateIframeSpy).not.toHaveBeenCalled(); expect(getOrCreateIframeSpy).not.toHaveBeenCalled();
}); });
}); });
});
describe('checkAuthMultiple', () => { describe('checkAuthMultiple', () => {
it('uses config with matching state when url has state param and config with state param is stored', async () => { it('uses config with matching state when url has state param and config with state param is stored', async () => {
@ -823,21 +790,20 @@ describe('CheckAuthService', () => {
); );
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig'); const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
checkAuthService.checkAuthMultiple(allConfigs).subscribe((result) => { const result = await lastValueFrom(checkAuthService.checkAuthMultiple(allConfigs));
expect(Array.isArray(result)).toBe(true); expect(Array.isArray(result)).toBe(true);;
expect(spy).toHaveBeenCalledTimes(2); expect(spy).toHaveBeenCalledTimes(2);;
expect(vi.mocked(spy).mock.calls[0]).toEqual([ expect(vi.mocked(spy).mock.calls[0]).toEqual([
allConfigs[0]!, allConfigs[0]!,
allConfigs, allConfigs,
undefined, undefined,
]); ]);;
expect(vi.mocked(spy).mock.calls[1]).toEqual([ expect(vi.mocked(spy).mock.calls[1]).toEqual([
allConfigs[1], allConfigs[1],
allConfigs, allConfigs,
undefined, undefined,
]); ]);
}); });
});
it('uses config from passed configId if configId was passed and returns all results', async () => { it('uses config from passed configId if configId was passed and returns all results', async () => {
vi.spyOn( vi.spyOn(
@ -852,8 +818,8 @@ describe('CheckAuthService', () => {
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig'); const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
checkAuthService.checkAuthMultiple(allConfigs).subscribe((result) => { const result = await lastValueFrom(checkAuthService.checkAuthMultiple(allConfigs));
expect(Array.isArray(result)).toBe(true); expect(Array.isArray(result)).toBe(true);;
expect(spy).toBeCalledWith([ expect(spy).toBeCalledWith([
[ [
{ configId: 'configId1', authority: 'some-authority1' }, { configId: 'configId1', authority: 'some-authority1' },
@ -867,7 +833,6 @@ describe('CheckAuthService', () => {
], ],
]); ]);
}); });
});
it('runs through all configs if no parameter is passed and has no state in url', async () => { it('runs through all configs if no parameter is passed and has no state in url', async () => {
vi.spyOn( vi.spyOn(
@ -882,21 +847,20 @@ describe('CheckAuthService', () => {
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig'); const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
checkAuthService.checkAuthMultiple(allConfigs).subscribe((result) => { const result = await lastValueFrom(checkAuthService.checkAuthMultiple(allConfigs));
expect(Array.isArray(result)).toBe(true); expect(Array.isArray(result)).toBe(true);;
expect(spy).toHaveBeenCalledTimes(2); expect(spy).toHaveBeenCalledTimes(2);;
expect(vi.mocked(spy).mock.calls[0]).toEqual([ expect(vi.mocked(spy).mock.calls[0]).toEqual([
{ configId: 'configId1', authority: 'some-authority1' }, { configId: 'configId1', authority: 'some-authority1' },
allConfigs, allConfigs,
undefined, undefined,
]); ]);;
expect(vi.mocked(spy).mock.calls[1]).toEqual([ expect(vi.mocked(spy).mock.calls[1]).toEqual([
{ configId: 'configId2', authority: 'some-authority2' }, { configId: 'configId2', authority: 'some-authority2' },
allConfigs, allConfigs,
undefined, undefined,
]); ]);
}); });
});
it('throws error if url has state param but no config could be found', async () => { it('throws error if url has state param but no config could be found', async () => {
vi.spyOn( vi.spyOn(

View File

@ -83,24 +83,22 @@ describe('AutoLoginPartialRoutesGuard', () => {
); );
const loginSpy = vi.spyOn(loginService, 'login'); const loginSpy = vi.spyOn(loginService, 'login');
guard await lastValueFrom(guard
.canActivate( .canActivate(
{} as ActivatedRouteSnapshot, {} as ActivatedRouteSnapshot,
{ url: 'some-url1' } as RouterStateSnapshot { url: 'some-url1' } as RouterStateSnapshot
) ));
.subscribe(() => {
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'some-url1' 'some-url1'
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
configId: 'configId1', configId: 'configId1',
}); });;
expect( expect(
checkSavedRedirectRouteAndNavigateSpy checkSavedRedirectRouteAndNavigateSpy
).not.toHaveBeenCalled(); ).not.toHaveBeenCalled();
}); });
});
it('should save current route and call `login` if not authenticated already and add custom params', async () => { it('should save current route and call `login` if not authenticated already and add custom params', async () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
@ -116,25 +114,23 @@ describe('AutoLoginPartialRoutesGuard', () => {
); );
const loginSpy = vi.spyOn(loginService, 'login'); const loginSpy = vi.spyOn(loginService, 'login');
guard await lastValueFrom(guard
.canActivate( .canActivate(
{ data: { custom: 'param' } } as unknown as ActivatedRouteSnapshot, { data: { custom: 'param' } } as unknown as ActivatedRouteSnapshot,
{ url: 'some-url1' } as RouterStateSnapshot { url: 'some-url1' } as RouterStateSnapshot
) ));
.subscribe(() => {
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'some-url1' 'some-url1'
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith( expect(loginSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
{ customParams: { custom: 'param' } } { customParams: { custom: 'param' } }
); );;
expect( expect(
checkSavedRedirectRouteAndNavigateSpy checkSavedRedirectRouteAndNavigateSpy
).not.toHaveBeenCalled(); ).not.toHaveBeenCalled();
}); });
});
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => { it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
@ -150,20 +146,18 @@ describe('AutoLoginPartialRoutesGuard', () => {
); );
const loginSpy = vi.spyOn(loginService, 'login'); const loginSpy = vi.spyOn(loginService, 'login');
guard await lastValueFrom(guard
.canActivate( .canActivate(
{} as ActivatedRouteSnapshot, {} as ActivatedRouteSnapshot,
{ url: 'some-url1' } as RouterStateSnapshot { url: 'some-url1' } as RouterStateSnapshot
) ));
.subscribe(() => { expect(saveRedirectRouteSpy).not.toHaveBeenCalled();;
expect(saveRedirectRouteSpy).not.toHaveBeenCalled(); expect(loginSpy).not.toHaveBeenCalled();;
expect(loginSpy).not.toHaveBeenCalled();
expect( expect(
checkSavedRedirectRouteAndNavigateSpy checkSavedRedirectRouteAndNavigateSpy
).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' }); ).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
}); });
}); });
});
describe('canActivateChild', () => { describe('canActivateChild', () => {
it('should save current route and call `login` if not authenticated already', async () => { it('should save current route and call `login` if not authenticated already', async () => {
@ -180,24 +174,22 @@ describe('AutoLoginPartialRoutesGuard', () => {
); );
const loginSpy = vi.spyOn(loginService, 'login'); const loginSpy = vi.spyOn(loginService, 'login');
guard await lastValueFrom(guard
.canActivateChild( .canActivateChild(
{} as ActivatedRouteSnapshot, {} as ActivatedRouteSnapshot,
{ url: 'some-url1' } as RouterStateSnapshot { url: 'some-url1' } as RouterStateSnapshot
) ));
.subscribe(() => {
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'some-url1' 'some-url1'
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
configId: 'configId1', configId: 'configId1',
}); });;
expect( expect(
checkSavedRedirectRouteAndNavigateSpy checkSavedRedirectRouteAndNavigateSpy
).not.toHaveBeenCalled(); ).not.toHaveBeenCalled();
}); });
});
it('should save current route and call `login` if not authenticated already with custom params', async () => { it('should save current route and call `login` if not authenticated already with custom params', async () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
@ -213,25 +205,23 @@ describe('AutoLoginPartialRoutesGuard', () => {
); );
const loginSpy = vi.spyOn(loginService, 'login'); const loginSpy = vi.spyOn(loginService, 'login');
guard await lastValueFrom(guard
.canActivateChild( .canActivateChild(
{ data: { custom: 'param' } } as unknown as ActivatedRouteSnapshot, { data: { custom: 'param' } } as unknown as ActivatedRouteSnapshot,
{ url: 'some-url1' } as RouterStateSnapshot { url: 'some-url1' } as RouterStateSnapshot
) ));
.subscribe(() => {
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'some-url1' 'some-url1'
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith( expect(loginSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
{ customParams: { custom: 'param' } } { customParams: { custom: 'param' } }
); );;
expect( expect(
checkSavedRedirectRouteAndNavigateSpy checkSavedRedirectRouteAndNavigateSpy
).not.toHaveBeenCalled(); ).not.toHaveBeenCalled();
}); });
});
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => { it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
@ -247,20 +237,18 @@ describe('AutoLoginPartialRoutesGuard', () => {
); );
const loginSpy = vi.spyOn(loginService, 'login'); const loginSpy = vi.spyOn(loginService, 'login');
guard await lastValueFrom(guard
.canActivateChild( .canActivateChild(
{} as ActivatedRouteSnapshot, {} as ActivatedRouteSnapshot,
{ url: 'some-url1' } as RouterStateSnapshot { url: 'some-url1' } as RouterStateSnapshot
) ));
.subscribe(() => { expect(saveRedirectRouteSpy).not.toHaveBeenCalled();;
expect(saveRedirectRouteSpy).not.toHaveBeenCalled(); expect(loginSpy).not.toHaveBeenCalled();;
expect(loginSpy).not.toHaveBeenCalled();
expect( expect(
checkSavedRedirectRouteAndNavigateSpy checkSavedRedirectRouteAndNavigateSpy
).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' }); ).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
}); });
}); });
});
describe('canLoad', () => { describe('canLoad', () => {
it('should save current route (empty) and call `login` if not authenticated already', async () => { it('should save current route (empty) and call `login` if not authenticated already', async () => {
@ -277,17 +265,16 @@ describe('AutoLoginPartialRoutesGuard', () => {
); );
const loginSpy = vi.spyOn(loginService, 'login'); const loginSpy = vi.spyOn(loginService, 'login');
guard.canLoad().subscribe(() => { await lastValueFrom(guard.canLoad());
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'' ''
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
configId: 'configId1', configId: 'configId1',
}); });;
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled(); expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
}); });
});
it('should save current route (with router extractedUrl) and call `login` if not authenticated already', async () => { it('should save current route (with router extractedUrl) and call `login` if not authenticated already', async () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
@ -314,17 +301,16 @@ describe('AutoLoginPartialRoutesGuard', () => {
trigger: 'imperative', trigger: 'imperative',
}); });
guard.canLoad().subscribe(() => { await lastValueFrom(guard.canLoad());
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'some-url12/with/some-param?queryParam=true' 'some-url12/with/some-param?queryParam=true'
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
configId: 'configId1', configId: 'configId1',
}); });;
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled(); expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
}); });
});
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => { it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
@ -340,16 +326,15 @@ describe('AutoLoginPartialRoutesGuard', () => {
); );
const loginSpy = vi.spyOn(loginService, 'login'); const loginSpy = vi.spyOn(loginService, 'login');
guard.canLoad().subscribe(() => { await lastValueFrom(guard.canLoad());
expect(saveRedirectRouteSpy).not.toHaveBeenCalled(); expect(saveRedirectRouteSpy).not.toHaveBeenCalled();;
expect(loginSpy).not.toHaveBeenCalled(); expect(loginSpy).not.toHaveBeenCalled();;
expect( expect(
checkSavedRedirectRouteAndNavigateSpy checkSavedRedirectRouteAndNavigateSpy
).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' }); ).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
}); });
}); });
}); });
});
describe('functional', () => { describe('functional', () => {
describe('autoLoginPartialRoutesGuard', () => { describe('autoLoginPartialRoutesGuard', () => {
@ -398,17 +383,16 @@ describe('AutoLoginPartialRoutesGuard', () => {
autoLoginPartialRoutesGuard autoLoginPartialRoutesGuard
); );
guard$.subscribe(() => { await lastValueFrom(guard$);
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'' ''
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
configId: 'configId1', configId: 'configId1',
}); });;
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled(); expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
}); });
});
it('should save current route (with router extractedUrl) and call `login` if not authenticated already', async () => { it('should save current route (with router extractedUrl) and call `login` if not authenticated already', async () => {
vi.spyOn(router, 'getCurrentNavigation').mockReturnValue({ vi.spyOn(router, 'getCurrentNavigation').mockReturnValue({
@ -439,17 +423,16 @@ describe('AutoLoginPartialRoutesGuard', () => {
autoLoginPartialRoutesGuard autoLoginPartialRoutesGuard
); );
guard$.subscribe(() => { await lastValueFrom(guard$);
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'some-url12/with/some-param?queryParam=true' 'some-url12/with/some-param?queryParam=true'
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
configId: 'configId1', configId: 'configId1',
}); });;
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled(); expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
}); });
});
it('should save current route and call `login` if not authenticated already and add custom params', async () => { it('should save current route and call `login` if not authenticated already and add custom params', async () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
@ -471,18 +454,17 @@ describe('AutoLoginPartialRoutesGuard', () => {
} as unknown as ActivatedRouteSnapshot) } as unknown as ActivatedRouteSnapshot)
); );
guard$.subscribe(() => { await lastValueFrom(guard$);
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'' ''
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith( expect(loginSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
{ customParams: { custom: 'param' } } { customParams: { custom: 'param' } }
); );;
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled(); expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
}); });
});
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => { it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
@ -502,15 +484,14 @@ describe('AutoLoginPartialRoutesGuard', () => {
autoLoginPartialRoutesGuard autoLoginPartialRoutesGuard
); );
guard$.subscribe(() => { await lastValueFrom(guard$);
expect(saveRedirectRouteSpy).not.toHaveBeenCalled(); expect(saveRedirectRouteSpy).not.toHaveBeenCalled();;
expect(loginSpy).not.toHaveBeenCalled(); expect(loginSpy).not.toHaveBeenCalled();;
expect( expect(
checkSavedRedirectRouteAndNavigateSpy checkSavedRedirectRouteAndNavigateSpy
).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' }); ).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
}); });
}); });
});
describe('autoLoginPartialRoutesGuardWithConfig', () => { describe('autoLoginPartialRoutesGuardWithConfig', () => {
let loginService: LoginService; let loginService: LoginService;
@ -556,17 +537,16 @@ describe('AutoLoginPartialRoutesGuard', () => {
autoLoginPartialRoutesGuardWithConfig('configId1') autoLoginPartialRoutesGuardWithConfig('configId1')
); );
guard$.subscribe(() => { await lastValueFrom(guard$);
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith( expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
{ configId: 'configId1' }, { configId: 'configId1' },
'' ''
); );;
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({ expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
configId: 'configId1', configId: 'configId1',
}); });;
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled(); expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
}); });
}); });
}); });
}); });
});

View File

@ -85,16 +85,14 @@ describe('CodeFlowCallbackService ', () => {
triggerAuthorizationResultEvent: true, triggerAuthorizationResultEvent: true,
}; };
codeFlowCallbackService await lastValueFrom(codeFlowCallbackService
.authenticatedCallbackWithCode('some-url2', config, [config]) .authenticatedCallbackWithCode('some-url2', config, [config]));
.subscribe(() => {
expect(spy).toHaveBeenCalledExactlyOnceWith('some-url2', config, [ expect(spy).toHaveBeenCalledExactlyOnceWith('some-url2', config, [
config, config,
]); ]);;
expect(routerSpy).not.toHaveBeenCalled(); expect(routerSpy).not.toHaveBeenCalled();;
expect(flowsDataSpy).toHaveBeenCalled(); expect(flowsDataSpy).toHaveBeenCalled();
}); });
});
it('calls router and resetCodeFlowInProgress if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => { it('calls router and resetCodeFlowInProgress if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => {
const callbackContext = { const callbackContext = {
@ -122,16 +120,14 @@ describe('CodeFlowCallbackService ', () => {
postLoginRoute: 'postLoginRoute', postLoginRoute: 'postLoginRoute',
}; };
codeFlowCallbackService await lastValueFrom(codeFlowCallbackService
.authenticatedCallbackWithCode('some-url3', config, [config]) .authenticatedCallbackWithCode('some-url3', config, [config]));
.subscribe(() => {
expect(spy).toHaveBeenCalledExactlyOnceWith('some-url3', config, [ expect(spy).toHaveBeenCalledExactlyOnceWith('some-url3', config, [
config, config,
]); ]);;
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute'); expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');;
expect(flowsDataSpy).toHaveBeenCalled(); expect(flowsDataSpy).toHaveBeenCalled();
}); });
});
it('resetSilentRenewRunning, resetCodeFlowInProgress and stopPeriodicallTokenCheck in case of error', async () => { it('resetSilentRenewRunning, resetCodeFlowInProgress and stopPeriodicallTokenCheck in case of error', async () => {
vi.spyOn(flowsService, 'processCodeFlowCallback').mockReturnValue( vi.spyOn(flowsService, 'processCodeFlowCallback').mockReturnValue(

View File

@ -81,17 +81,15 @@ describe('ImplicitFlowCallbackService ', () => {
triggerAuthorizationResultEvent: true, triggerAuthorizationResultEvent: true,
}; };
implicitFlowCallbackService await lastValueFrom(implicitFlowCallbackService
.authenticatedImplicitFlowCallback(config, [config], 'some-hash') .authenticatedImplicitFlowCallback(config, [config], 'some-hash'));
.subscribe(() => {
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(
config, config,
[config], [config],
'some-hash' 'some-hash'
); );;
expect(routerSpy).not.toHaveBeenCalled(); expect(routerSpy).not.toHaveBeenCalled();
}); });
});
it('calls router if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => { it('calls router if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => {
const callbackContext = { const callbackContext = {
@ -115,17 +113,15 @@ describe('ImplicitFlowCallbackService ', () => {
postLoginRoute: 'postLoginRoute', postLoginRoute: 'postLoginRoute',
}; };
implicitFlowCallbackService await lastValueFrom(implicitFlowCallbackService
.authenticatedImplicitFlowCallback(config, [config], 'some-hash') .authenticatedImplicitFlowCallback(config, [config], 'some-hash'));
.subscribe(() => {
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(
config, config,
[config], [config],
'some-hash' 'some-hash'
); );;
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute'); expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
}); });
});
it('resetSilentRenewRunning and stopPeriodicallyTokenCheck in case of error', async () => { it('resetSilentRenewRunning and stopPeriodicallyTokenCheck in case of error', async () => {
vi.spyOn(flowsService, 'processImplicitFlowCallback').mockReturnValue( vi.spyOn(flowsService, 'processImplicitFlowCallback').mockReturnValue(

View File

@ -1,5 +1,5 @@
import { TestBed } from '@/testing'; import { TestBed } from '@/testing';
import { of, throwError } from 'rxjs'; import { lastValueFrom, of, throwError } from 'rxjs';
import { vi } from 'vitest'; import { vi } from 'vitest';
import type { CallbackContext } from '../flows/callback-context'; import type { CallbackContext } from '../flows/callback-context';
import { FlowsService } from '../flows/flows.service'; import { FlowsService } from '../flows/flows.service';
@ -44,14 +44,14 @@ describe('RefreshSessionRefreshTokenService', () => {
.spyOn(flowsService, 'processRefreshToken') .spyOn(flowsService, 'processRefreshToken')
.mockReturnValue(of({} as CallbackContext)); .mockReturnValue(of({} as CallbackContext));
refreshSessionRefreshTokenService await lastValueFrom(
.refreshSessionWithRefreshTokens({ configId: 'configId1' }, [ refreshSessionRefreshTokenService.refreshSessionWithRefreshTokens(
{ configId: 'configId1' }, { configId: 'configId1' },
]) [{ configId: 'configId1' }]
.subscribe(() => { )
);
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('resetAuthorizationData in case of error', async () => { it('resetAuthorizationData in case of error', async () => {
vi.spyOn(flowsService, 'processRefreshToken').mockReturnValue( vi.spyOn(flowsService, 'processRefreshToken').mockReturnValue(

View File

@ -91,16 +91,19 @@ describe('RefreshSessionService ', () => {
const extraCustomParams = { extra: 'custom' }; const extraCustomParams = { extra: 'custom' };
refreshSessionService await lastValueFrom(
.userForceRefreshSession(allConfigs[0]!, allConfigs, extraCustomParams) refreshSessionService.userForceRefreshSession(
.subscribe(() => { allConfigs[0]!,
allConfigs,
extraCustomParams
)
);
expect(writeSpy).toHaveBeenCalledExactlyOnceWith( expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
'storageCustomParamsRefresh', 'storageCustomParamsRefresh',
extraCustomParams, extraCustomParams,
allConfigs[0] allConfigs[0]
); );
}); });
});
it('should persist storageCustomParamsAuthRequest when extra custom params given and useRefreshToken is false', async () => { it('should persist storageCustomParamsAuthRequest when extra custom params given and useRefreshToken is false', async () => {
vi.spyOn( vi.spyOn(
@ -125,16 +128,19 @@ describe('RefreshSessionService ', () => {
const extraCustomParams = { extra: 'custom' }; const extraCustomParams = { extra: 'custom' };
refreshSessionService await lastValueFrom(
.userForceRefreshSession(allConfigs[0]!, allConfigs, extraCustomParams) refreshSessionService.userForceRefreshSession(
.subscribe(() => { allConfigs[0]!,
allConfigs,
extraCustomParams
)
);
expect(writeSpy).toHaveBeenCalledExactlyOnceWith( expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
'storageCustomParamsAuthRequest', 'storageCustomParamsAuthRequest',
extraCustomParams, extraCustomParams,
allConfigs[0] allConfigs[0]
); );
}); });
});
it('should NOT persist customparams if no customparams are given', async () => { it('should NOT persist customparams if no customparams are given', async () => {
vi.spyOn( vi.spyOn(
@ -157,12 +163,14 @@ describe('RefreshSessionService ', () => {
]; ];
const writeSpy = vi.spyOn(storagePersistenceService, 'write'); const writeSpy = vi.spyOn(storagePersistenceService, 'write');
refreshSessionService await lastValueFrom(
.userForceRefreshSession(allConfigs[0]!, allConfigs) refreshSessionService.userForceRefreshSession(
.subscribe(() => { allConfigs[0]!,
allConfigs
)
);
expect(writeSpy).not.toHaveBeenCalled(); expect(writeSpy).not.toHaveBeenCalled();
}); });
});
it('should call resetSilentRenewRunning in case of an error', async () => { it('should call resetSilentRenewRunning in case of an error', async () => {
vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue( vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
@ -247,13 +255,12 @@ describe('RefreshSessionService ', () => {
}, },
]; ];
refreshSessionService const result = await lastValueFrom(
.forceRefreshSession(allConfigs[0]!, allConfigs) refreshSessionService.forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => { );
expect(result.idToken).toEqual('id-token'); expect(result.idToken).toEqual('id-token');
expect(result.accessToken).toEqual('access-token'); expect(result.accessToken).toEqual('access-token');
}); });
});
it('only calls start refresh session and returns null if auth is false', async () => { it('only calls start refresh session and returns null if auth is false', async () => {
vi.spyOn( vi.spyOn(
@ -274,9 +281,9 @@ describe('RefreshSessionService ', () => {
}, },
]; ];
refreshSessionService const result = await lastValueFrom(
.forceRefreshSession(allConfigs[0]!, allConfigs) refreshSessionService.forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => { );
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: false, isAuthenticated: false,
errorMessage: '', errorMessage: '',
@ -286,7 +293,6 @@ describe('RefreshSessionService ', () => {
configId: 'configId1', configId: 'configId1',
}); });
}); });
});
it('calls start refresh session and waits for completed, returns idtoken and accesstoken if auth is true', async () => { it('calls start refresh session and waits for completed, returns idtoken and accesstoken if auth is true', async () => {
vi.spyOn( vi.spyOn(
@ -318,13 +324,12 @@ describe('RefreshSessionService ', () => {
}, },
]; ];
refreshSessionService const result = await lastValueFrom(
.forceRefreshSession(allConfigs[0]!, allConfigs) refreshSessionService.forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => { );
expect(result.idToken).toBeDefined(); expect(result.idToken).toBeDefined();
expect(result.accessToken).toBeDefined(); expect(result.accessToken).toBeDefined();
}); });
});
it('calls start refresh session and waits for completed, returns LoginResponse if auth is false', async () => { it('calls start refresh session and waits for completed, returns LoginResponse if auth is false', async () => {
vi.spyOn( vi.spyOn(
@ -349,9 +354,9 @@ describe('RefreshSessionService ', () => {
}, },
]; ];
refreshSessionService const result = await lastValueFrom(
.forceRefreshSession(allConfigs[0]!, allConfigs) refreshSessionService.forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => { );
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: false, isAuthenticated: false,
errorMessage: '', errorMessage: '',
@ -361,7 +366,6 @@ describe('RefreshSessionService ', () => {
configId: 'configId1', configId: 'configId1',
}); });
}); });
});
it('occurs timeout error and retry mechanism exhausted max retry count throws error', async () => { it('occurs timeout error and retry mechanism exhausted max retry count throws error', async () => {
vi.spyOn( vi.spyOn(
@ -483,9 +487,9 @@ describe('RefreshSessionService ', () => {
'refreshSessionWithIFrameCompleted$' 'refreshSessionWithIFrameCompleted$'
).mockReturnValue(of(null)); ).mockReturnValue(of(null));
refreshSessionService const result = await lastValueFrom(
.forceRefreshSession(allConfigs[0]!, allConfigs) refreshSessionService.forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => { );
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: false, isAuthenticated: false,
errorMessage: '', errorMessage: '',
@ -495,7 +499,6 @@ describe('RefreshSessionService ', () => {
configId: 'configId1', configId: 'configId1',
}); });
}); });
});
it('return value only returns once', async () => { it('return value only returns once', async () => {
const allConfigs = [ const allConfigs = [
@ -528,9 +531,9 @@ describe('RefreshSessionService ', () => {
.spyOn(authStateService, 'areAuthStorageTokensValid') .spyOn(authStateService, 'areAuthStorageTokensValid')
.mockReturnValue(true); .mockReturnValue(true);
refreshSessionService const result = await lastValueFrom(
.forceRefreshSession(allConfigs[0]!, allConfigs) refreshSessionService.forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe((result) => { );
expect(result).toEqual({ expect(result).toEqual({
idToken: 'some-id_token', idToken: 'some-id_token',
accessToken: 'some-access_token', accessToken: 'some-access_token',
@ -542,28 +545,25 @@ describe('RefreshSessionService ', () => {
}); });
}); });
}); });
});
describe('startRefreshSession', () => { describe('startRefreshSession', () => {
it('returns null if no auth well known endpoint defined', async () => { it('returns null if no auth well known endpoint defined', async () => {
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true); vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
(refreshSessionService as any) const result = await lastValueFrom(
.startRefreshSession() (refreshSessionService as any).startRefreshSession()
.subscribe((result: any) => { );
expect(result).toBe(null); expect(result).toBe(null);
}); });
});
it('returns null if silent renew Is running', async () => { it('returns null if silent renew Is running', async () => {
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true); vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
(refreshSessionService as any) const result = await lastValueFrom(
.startRefreshSession() (refreshSessionService as any).startRefreshSession()
.subscribe((result: any) => { );
expect(result).toBe(null); expect(result).toBe(null);
}); });
});
it('calls `setSilentRenewRunning` when should be executed', async () => { it('calls `setSilentRenewRunning` when should be executed', async () => {
const setSilentRenewRunningSpy = vi.spyOn( const setSilentRenewRunningSpy = vi.spyOn(
@ -592,12 +592,14 @@ describe('RefreshSessionService ', () => {
'refreshSessionWithRefreshTokens' 'refreshSessionWithRefreshTokens'
).mockReturnValue(of({} as CallbackContext)); ).mockReturnValue(of({} as CallbackContext));
(refreshSessionService as any) await lastValueFrom(
.startRefreshSession(allConfigs[0]!, allConfigs) (refreshSessionService as any).startRefreshSession(
.subscribe(() => { allConfigs[0]!,
allConfigs
)
);
expect(setSilentRenewRunningSpy).toHaveBeenCalled(); expect(setSilentRenewRunningSpy).toHaveBeenCalled();
}); });
});
it('calls refreshSessionWithRefreshTokens when current flow is codeflow with refresh tokens', async () => { it('calls refreshSessionWithRefreshTokens when current flow is codeflow with refresh tokens', async () => {
vi.spyOn(flowsDataService, 'setSilentRenewRunning'); vi.spyOn(flowsDataService, 'setSilentRenewRunning');
@ -625,12 +627,14 @@ describe('RefreshSessionService ', () => {
) )
.mockReturnValue(of({} as CallbackContext)); .mockReturnValue(of({} as CallbackContext));
(refreshSessionService as any) await lastValueFrom(
.startRefreshSession(allConfigs[0]!, allConfigs) (refreshSessionService as any).startRefreshSession(
.subscribe(() => { allConfigs[0]!,
allConfigs
)
);
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled(); expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();
}); });
});
it('calls refreshSessionWithIframe when current flow is NOT codeflow with refresh tokens', async () => { it('calls refreshSessionWithIframe when current flow is NOT codeflow with refresh tokens', async () => {
vi.spyOn(flowsDataService, 'setSilentRenewRunning'); vi.spyOn(flowsDataService, 'setSilentRenewRunning');
@ -662,12 +666,14 @@ describe('RefreshSessionService ', () => {
.spyOn(refreshSessionIframeService, 'refreshSessionWithIframe') .spyOn(refreshSessionIframeService, 'refreshSessionWithIframe')
.mockReturnValue(of(false)); .mockReturnValue(of(false));
(refreshSessionService as any) await lastValueFrom(
.startRefreshSession(allConfigs[0]!, allConfigs) (refreshSessionService as any).startRefreshSession(
.subscribe(() => { allConfigs[0]!,
allConfigs
)
);
expect(refreshSessionWithRefreshTokensSpy).not.toHaveBeenCalled(); expect(refreshSessionWithRefreshTokensSpy).not.toHaveBeenCalled();
expect(refreshSessionWithIframeSpy).toHaveBeenCalled(); expect(refreshSessionWithIframeSpy).toHaveBeenCalled();
}); });
}); });
}); });
});

View File

@ -1,5 +1,5 @@
import { TestBed } from '@/testing'; import { TestBed } from '@/testing';
import { of, throwError } from 'rxjs'; import { lastValueFrom, of, throwError } from 'rxjs';
import { vi } from 'vitest'; import { vi } from 'vitest';
import { DataService } from '../../api/data.service'; import { DataService } from '../../api/data.service';
import { LoggerService } from '../../logging/logger.service'; import { LoggerService } from '../../logging/logger.service';
@ -59,15 +59,13 @@ describe('AuthWellKnownDataService', () => {
const urlWithoutSuffix = 'myUrl'; const urlWithoutSuffix = 'myUrl';
const urlWithSuffix = `${urlWithoutSuffix}/.well-known/openid-configuration`; const urlWithSuffix = `${urlWithoutSuffix}/.well-known/openid-configuration`;
(service as any) await lastValueFrom(
.getWellKnownDocument(urlWithoutSuffix, { configId: 'configId1' }) (service as any).getWellKnownDocument(urlWithoutSuffix, {
.subscribe(() => {
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
urlWithSuffix,
{
configId: 'configId1', configId: 'configId1',
} })
); );
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(urlWithSuffix, {
configId: 'configId1',
}); });
}); });
@ -77,15 +75,13 @@ describe('AuthWellKnownDataService', () => {
.mockReturnValue(of(null)); .mockReturnValue(of(null));
const urlWithSuffix = `myUrl/.well-known/openid-configuration`; const urlWithSuffix = `myUrl/.well-known/openid-configuration`;
(service as any) await lastValueFrom(
.getWellKnownDocument(urlWithSuffix, { configId: 'configId1' }) (service as any).getWellKnownDocument(urlWithSuffix, {
.subscribe(() => {
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
urlWithSuffix,
{
configId: 'configId1', configId: 'configId1',
} })
); );
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(urlWithSuffix, {
configId: 'configId1',
}); });
}); });
@ -95,15 +91,13 @@ describe('AuthWellKnownDataService', () => {
.mockReturnValue(of(null)); .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`;
(service as any) await lastValueFrom(
.getWellKnownDocument(urlWithSuffix, { configId: 'configId1' }) (service as any).getWellKnownDocument(urlWithSuffix, {
.subscribe(() => {
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
urlWithSuffix,
{
configId: 'configId1', configId: 'configId1',
} })
); );
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(urlWithSuffix, {
configId: 'configId1',
}); });
}); });
@ -114,19 +108,15 @@ describe('AuthWellKnownDataService', () => {
const urlWithoutSuffix = `myUrl`; const urlWithoutSuffix = `myUrl`;
const urlWithSuffix = `${urlWithoutSuffix}/.well-known/test-openid-configuration`; const urlWithSuffix = `${urlWithoutSuffix}/.well-known/test-openid-configuration`;
(service as any) await lastValueFrom(
.getWellKnownDocument(urlWithoutSuffix, { (service as any).getWellKnownDocument(urlWithoutSuffix, {
configId: 'configId1', configId: 'configId1',
authWellknownUrlSuffix: '/.well-known/test-openid-configuration', authWellknownUrlSuffix: '/.well-known/test-openid-configuration',
}) })
.subscribe(() => { );
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith( expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(urlWithSuffix, {
urlWithSuffix,
{
configId: 'configId1', configId: 'configId1',
authWellknownUrlSuffix: '/.well-known/test-openid-configuration', authWellknownUrlSuffix: '/.well-known/test-openid-configuration',
}
);
}); });
}); });
@ -193,17 +183,16 @@ describe('AuthWellKnownDataService', () => {
const spy = vi.spyOn(service as any, 'getWellKnownDocument')(); const spy = vi.spyOn(service as any, 'getWellKnownDocument')();
service const result = await lastValueFrom(
.getWellKnownEndPointsForConfig({ service.getWellKnownEndPointsForConfig({
configId: 'configId1', configId: 'configId1',
authWellknownEndpointUrl: 'any-url', authWellknownEndpointUrl: 'any-url',
}) })
.subscribe((result) => { );
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
expect((result as any).jwks_uri).toBeUndefined(); expect((result as any).jwks_uri).toBeUndefined();
expect(result.jwksUri).toBe('jwks_uri'); expect(result.jwksUri).toBe('jwks_uri');
}); });
});
it('throws error and logs if no authwellknownUrl is given', async () => { it('throws error and logs if no authwellknownUrl is given', async () => {
const loggerSpy = vi.spyOn(loggerService, 'logError'); const loggerSpy = vi.spyOn(loggerService, 'logError');
@ -234,8 +223,8 @@ describe('AuthWellKnownDataService', () => {
jwksUri: DUMMY_WELL_KNOWN_DOCUMENT.jwks_uri, jwksUri: DUMMY_WELL_KNOWN_DOCUMENT.jwks_uri,
}; };
service const result = await lastValueFrom(
.getWellKnownEndPointsForConfig({ service.getWellKnownEndPointsForConfig({
configId: 'configId1', configId: 'configId1',
authWellknownEndpointUrl: 'any-url', authWellknownEndpointUrl: 'any-url',
authWellknownEndpoints: { authWellknownEndpoints: {
@ -243,9 +232,8 @@ describe('AuthWellKnownDataService', () => {
revocationEndpoint: 'config-revocationEndpoint', revocationEndpoint: 'config-revocationEndpoint',
}, },
}) })
.subscribe((result) => { );
expect(result).toEqual(jasmine.objectContaining(expected)); expect(result).toEqual(jasmine.objectContaining(expected));
}); });
}); });
}); });
});

View File

@ -1,5 +1,5 @@
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing'; import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
import { of, throwError } from 'rxjs'; import { lastValueFrom, of, throwError } from 'rxjs';
import { vi } from 'vitest'; import { vi } from 'vitest';
import { EventTypes } from '../../public-events/event-types'; import { EventTypes } from '../../public-events/event-types';
import { PublicEventsService } from '../../public-events/public-events.service'; import { PublicEventsService } from '../../public-events/public-events.service';
@ -57,14 +57,13 @@ describe('AuthWellKnownService', () => {
() => ({ issuer: 'anything' }) () => ({ issuer: 'anything' })
); );
service const result = await lastValueFrom(
.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' }) service.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
.subscribe((result) => { );
expect(storagePersistenceService.read).not.toHaveBeenCalled(); expect(storagePersistenceService.read).not.toHaveBeenCalled();
expect(dataServiceSpy).toHaveBeenCalled(); expect(dataServiceSpy).toHaveBeenCalled();
expect(result).toEqual({ issuer: 'anything' }); expect(result).toEqual({ issuer: 'anything' });
}); });
});
it('getAuthWellKnownEndPoints stored the result if http call is made', async () => { it('getAuthWellKnownEndPoints stored the result if http call is made', async () => {
const dataServiceSpy = vi const dataServiceSpy = vi
@ -78,14 +77,13 @@ describe('AuthWellKnownService', () => {
); );
const storeSpy = vi.spyOn(service, 'storeWellKnownEndpoints'); const storeSpy = vi.spyOn(service, 'storeWellKnownEndpoints');
service const result = await lastValueFrom(
.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' }) service.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
.subscribe((result) => { );
expect(dataServiceSpy).toHaveBeenCalled(); expect(dataServiceSpy).toHaveBeenCalled();
expect(storeSpy).toHaveBeenCalled(); expect(storeSpy).toHaveBeenCalled();
expect(result).toEqual({ issuer: 'anything' }); expect(result).toEqual({ issuer: 'anything' });
}); });
});
it('throws `ConfigLoadingFailed` event when error happens from http', async () => { it('throws `ConfigLoadingFailed` event when error happens from http', async () => {
vi.spyOn(dataService, 'getWellKnownEndPointsForConfig').mockReturnValue( vi.spyOn(dataService, 'getWellKnownEndPointsForConfig').mockReturnValue(

View File

@ -1,5 +1,5 @@
import { TestBed } from '@/testing'; import { TestBed } from '@/testing';
import { of } from 'rxjs'; import { lastValueFrom, of } from 'rxjs';
import { vi } from 'vitest'; import { vi } from 'vitest';
import { LoggerService } from '../logging/logger.service'; import { LoggerService } from '../logging/logger.service';
import { EventTypes } from '../public-events/event-types'; import { EventTypes } from '../public-events/event-types';
@ -93,11 +93,12 @@ describe('Configuration Service', () => {
}; };
const spy = vi.spyOn(configService as any, 'loadConfigs'); const spy = vi.spyOn(configService as any, 'loadConfigs');
configService.getOpenIDConfiguration('configId1').subscribe((config) => { const config = await lastValueFrom(
configService.getOpenIDConfiguration('configId1')
);
expect(config).toBeTruthy(); expect(config).toBeTruthy();
expect(spy).not.toHaveBeenCalled(); expect(spy).not.toHaveBeenCalled();
}); });
});
it(`if config is NOT already saved 'loadConfigs' is called`, async () => { it(`if config is NOT already saved 'loadConfigs' is called`, async () => {
const configs = [{ configId: 'configId1' }, { configId: 'configId2' }]; const configs = [{ configId: 'configId1' }, { configId: 'configId2' }];
@ -107,11 +108,12 @@ describe('Configuration Service', () => {
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true); vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
configService.getOpenIDConfiguration('configId1').subscribe((config) => { const config = await lastValueFrom(
configService.getOpenIDConfiguration('configId1')
);
expect(config).toBeTruthy(); expect(config).toBeTruthy();
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
}); });
});
it('returns null if config is not valid', async () => { it('returns null if config is not valid', async () => {
const configs = [{ configId: 'configId1' }]; const configs = [{ configId: 'configId1' }];
@ -124,13 +126,14 @@ describe('Configuration Service', () => {
); );
const consoleSpy = vi.spyOn(console, 'warn'); const consoleSpy = vi.spyOn(console, 'warn');
configService.getOpenIDConfiguration('configId1').subscribe((config) => { const config = await lastValueFrom(
configService.getOpenIDConfiguration('configId1')
);
expect(config).toBeNull(); expect(config).toBeNull();
expect(consoleSpy).toHaveBeenCalledExactlyOnceWith( expect(consoleSpy).toHaveBeenCalledExactlyOnceWith(
`[oidc-client-rx] No configuration found for config id 'configId1'.` `[oidc-client-rx] No configuration found for config id 'configId1'.`
); );
}); });
});
it('returns null if configs are stored but not existing ID is passed', async () => { it('returns null if configs are stored but not existing ID is passed', async () => {
(configService as any).configsInternal = { (configService as any).configsInternal = {
@ -138,12 +141,11 @@ describe('Configuration Service', () => {
configId2: { configId: 'configId2' }, configId2: { configId: 'configId2' },
}; };
configService const config = await lastValueFrom(
.getOpenIDConfiguration('notExisting') configService.getOpenIDConfiguration('notExisting')
.subscribe((config) => { );
expect(config).toBeNull(); expect(config).toBeNull();
}); });
});
it('sets authWellKnownEndPoints on config if authWellKnownEndPoints is stored', async () => { it('sets authWellKnownEndPoints on config if authWellKnownEndPoints is stored', async () => {
const configs = [{ configId: 'configId1' }]; const configs = [{ configId: 'configId1' }];
@ -158,13 +160,14 @@ describe('Configuration Service', () => {
issuer: 'auth-well-known', issuer: 'auth-well-known',
}); });
configService.getOpenIDConfiguration('configId1').subscribe((config) => { const config = await lastValueFrom(
configService.getOpenIDConfiguration('configId1')
);
expect(config?.authWellknownEndpoints).toEqual({ expect(config?.authWellknownEndpoints).toEqual({
issuer: 'auth-well-known', issuer: 'auth-well-known',
}); });
expect(consoleSpy).not.toHaveBeenCalled(); expect(consoleSpy).not.toHaveBeenCalled();
}); });
});
it('fires ConfigLoaded if authWellKnownEndPoints is stored', async () => { it('fires ConfigLoaded if authWellKnownEndPoints is stored', async () => {
const configs = [{ configId: 'configId1' }]; const configs = [{ configId: 'configId1' }];
@ -179,13 +182,12 @@ describe('Configuration Service', () => {
const spy = vi.spyOn(publicEventsService, 'fireEvent'); const spy = vi.spyOn(publicEventsService, 'fireEvent');
configService.getOpenIDConfiguration('configId1').subscribe(() => { await lastValueFrom(configService.getOpenIDConfiguration('configId1'));
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(
EventTypes.ConfigLoaded, EventTypes.ConfigLoaded,
expect.anything() expect.anything()
); );
}); });
});
it('stores, uses and fires event when authwellknownendpoints are passed', async () => { it('stores, uses and fires event when authwellknownendpoints are passed', async () => {
const configs = [ const configs = [
@ -207,7 +209,9 @@ describe('Configuration Service', () => {
'storeWellKnownEndpoints' 'storeWellKnownEndpoints'
); );
configService.getOpenIDConfiguration('configId1').subscribe((config) => { const config = await lastValueFrom(
configService.getOpenIDConfiguration('configId1')
);
expect(config).toBeTruthy(); expect(config).toBeTruthy();
expect(fireEventSpy).toHaveBeenCalledExactlyOnceWith( expect(fireEventSpy).toHaveBeenCalledExactlyOnceWith(
EventTypes.ConfigLoaded, EventTypes.ConfigLoaded,
@ -221,7 +225,6 @@ describe('Configuration Service', () => {
); );
}); });
}); });
});
describe('getOpenIDConfigurations', () => { describe('getOpenIDConfigurations', () => {
it('returns correct result', async () => { it('returns correct result', async () => {
@ -234,11 +237,12 @@ describe('Configuration Service', () => {
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true); vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
configService.getOpenIDConfigurations('configId1').subscribe((result) => { const result = await lastValueFrom(
configService.getOpenIDConfigurations('configId1')
);
expect(result.allConfigs.length).toEqual(2); expect(result.allConfigs.length).toEqual(2);
expect(result.currentConfig).toBeTruthy(); expect(result.currentConfig).toBeTruthy();
}); });
});
it('created configId when configId is not set', async () => { it('created configId when configId is not set', async () => {
vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue( vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue(
@ -250,16 +254,15 @@ describe('Configuration Service', () => {
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true); vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
configService.getOpenIDConfigurations().subscribe((result) => { const result = await lastValueFrom(
configService.getOpenIDConfigurations()
);
expect(result.allConfigs.length).toEqual(2); expect(result.allConfigs.length).toEqual(2);
const allConfigIds = result.allConfigs.map((x) => x.configId); const allConfigIds = result.allConfigs.map((x) => x.configId);
expect(allConfigIds).toEqual(['0-clientId1', '1-clientId2']); expect(allConfigIds).toEqual(['0-clientId1', '1-clientId2']);
expect(result.currentConfig).toBeTruthy(); expect(result.currentConfig).toBeTruthy();
expect(result.currentConfig?.configId).toBeTruthy(); expect(result.currentConfig?.configId).toBeTruthy();
}); });
});
it('returns empty array if config is not valid', async () => { it('returns empty array if config is not valid', async () => {
vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue( vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue(
@ -273,14 +276,11 @@ describe('Configuration Service', () => {
false false
); );
configService await lastValueFrom(configService.getOpenIDConfigurations());
.getOpenIDConfigurations()
.subscribe(({ allConfigs, currentConfig }) => {
expect(allConfigs).toEqual([]); expect(allConfigs).toEqual([]);
expect(currentConfig).toBeNull(); expect(currentConfig).toBeNull();
}); });
}); });
});
describe('setSpecialCases', () => { describe('setSpecialCases', () => {
it('should set special cases when current platform is browser', () => { it('should set special cases when current platform is browser', () => {

View File

@ -1,5 +1,5 @@
import { waitForAsync } from '@/testing'; import { waitForAsync } from '@/testing';
import { of } from 'rxjs'; import { lastValueFrom, of } from 'rxjs';
import type { OpenIdConfiguration } from '../openid-configuration'; import type { OpenIdConfiguration } from '../openid-configuration';
import { StsConfigHttpLoader, StsConfigStaticLoader } from './config-loader'; import { StsConfigHttpLoader, StsConfigStaticLoader } from './config-loader';
@ -16,10 +16,9 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs(); const result$ = loader.loadConfigs();
result$.subscribe((result) => { const result = await lastValueFrom(result$);
expect(Array.isArray(result)).toBeTruthy(); expect(Array.isArray(result)).toBeTruthy();
}); });
});
it('returns an array if only one config is passed', async () => { it('returns an array if only one config is passed', async () => {
const loader = new StsConfigStaticLoader({ const loader = new StsConfigStaticLoader({
@ -28,12 +27,11 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs(); const result$ = loader.loadConfigs();
result$.subscribe((result) => { const result = await lastValueFrom(result$);
expect(Array.isArray(result)).toBeTruthy(); expect(Array.isArray(result)).toBeTruthy();
}); });
}); });
}); });
});
describe('StsConfigHttpLoader', () => { describe('StsConfigHttpLoader', () => {
describe('loadConfigs', () => { describe('loadConfigs', () => {
@ -46,12 +44,11 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs(); const result$ = loader.loadConfigs();
result$.subscribe((result) => { const result = await lastValueFrom(result$);
expect(Array.isArray(result)).toBeTruthy(); expect(Array.isArray(result)).toBeTruthy();
expect(result[0].configId).toBe('configId1'); expect(result[0].configId).toBe('configId1');
expect(result[1].configId).toBe('configId2'); expect(result[1].configId).toBe('configId2');
}); });
});
it('returns an array if an observable with a config array is passed', async () => { it('returns an array if an observable with a config array is passed', async () => {
const toPass = of([ const toPass = of([
@ -62,12 +59,11 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs(); const result$ = loader.loadConfigs();
result$.subscribe((result) => { const result = await lastValueFrom(result$);
expect(Array.isArray(result)).toBeTruthy(); expect(Array.isArray(result)).toBeTruthy();
expect(result[0].configId).toBe('configId1'); expect(result[0].configId).toBe('configId1');
expect(result[1].configId).toBe('configId2'); expect(result[1].configId).toBe('configId2');
}); });
});
it('returns an array if only one config is passed', async () => { it('returns an array if only one config is passed', async () => {
const loader = new StsConfigHttpLoader( const loader = new StsConfigHttpLoader(
@ -76,11 +72,10 @@ describe('ConfigLoader', () => {
const result$ = loader.loadConfigs(); const result$ = loader.loadConfigs();
result$.subscribe((result) => { const result = await lastValueFrom(result$);
expect(Array.isArray(result)).toBeTruthy(); expect(Array.isArray(result)).toBeTruthy();
expect(result[0].configId).toBe('configId1'); expect(result[0].configId).toBe('configId1');
}); });
}); });
}); });
}); });
});

View File

@ -98,13 +98,11 @@ describe('CodeFlowCallbackHandlerService', () => {
existingIdToken: null, existingIdToken: null,
} as CallbackContext; } as CallbackContext;
service const callbackContext = await lastValueFrom(service
.codeFlowCallback('test-url', { configId: 'configId1' }) .codeFlowCallback('test-url', { configId: 'configId1' }));
.subscribe((callbackContext) => {
expect(callbackContext).toEqual(expectedCallbackContext); expect(callbackContext).toEqual(expectedCallbackContext);
}); });
}); });
});
describe('codeFlowCodeRequest ', () => { describe('codeFlowCodeRequest ', () => {
const HTTP_ERROR = new HttpErrorResponse({}); const HTTP_ERROR = new HttpErrorResponse({});
@ -184,9 +182,8 @@ describe('CodeFlowCallbackHandlerService', () => {
'validateStateFromHashCallback' 'validateStateFromHashCallback'
).mockReturnValue(true); ).mockReturnValue(true);
service await lastValueFrom(service
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' }) .codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' }));
.subscribe(() => {
expect(postSpy).toHaveBeenCalledExactlyOnceWith( expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'tokenEndpoint', 'tokenEndpoint',
undefined, undefined,
@ -194,7 +191,6 @@ describe('CodeFlowCallbackHandlerService', () => {
expect.any(HttpHeaders) expect.any(HttpHeaders)
); );
}); });
});
it('calls url service with custom token params', async () => { it('calls url service with custom token params', async () => {
const urlServiceSpy = vi.spyOn( const urlServiceSpy = vi.spyOn(
@ -219,15 +215,13 @@ describe('CodeFlowCallbackHandlerService', () => {
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({})); const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
service await lastValueFrom(service
.codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config) .codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config));
.subscribe(() => {
expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, { expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, {
foo: 'bar', foo: 'bar',
}); });;
expect(postSpy).toHaveBeenCalledTimes(1); expect(postSpy).toHaveBeenCalledTimes(1);
}); });
});
it('calls dataService with correct headers if all params are good', async () => { it('calls dataService with correct headers if all params are good', async () => {
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({})); const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
@ -247,17 +241,14 @@ describe('CodeFlowCallbackHandlerService', () => {
'validateStateFromHashCallback' 'validateStateFromHashCallback'
).mockReturnValue(true); ).mockReturnValue(true);
service await lastValueFrom(service
.codeFlowCodeRequest({} as CallbackContext, config) .codeFlowCodeRequest({} as CallbackContext, config));
.subscribe(() => { const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders; expect(httpHeaders.has('Content-Type')).toBeTruthy();;
expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe( expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded' 'application/x-www-form-urlencoded'
); );
}); });
});
it('returns error in case of http error', async () => { it('returns error in case of http error', async () => {
vi.spyOn(dataService, 'post').mockReturnValue( vi.spyOn(dataService, 'post').mockReturnValue(

View File

@ -83,21 +83,18 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue( vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({ keys: [] } as JwtKeys) of({ keys: [] } as JwtKeys)
); );
service await lastValueFrom(service
.callbackHistoryAndResetJwtKeys( .callbackHistoryAndResetJwtKeys(
callbackContext, callbackContext,
allConfigs[0]!, allConfigs[0]!,
allConfigs allConfigs
) ));
.subscribe(() => {
expect(storagePersistenceServiceSpy).toBeCalledWith([ expect(storagePersistenceServiceSpy).toBeCalledWith([
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]], ['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
['jwtKeys', { keys: [] }, allConfigs[0]], ['jwtKeys', { keys: [] }, allConfigs[0]],
]); ]);;
// write authnResult & jwtKeys
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2); expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
}); });
});
it('writes refresh_token into the storage without reuse (refresh token rotation)', async () => { it('writes refresh_token into the storage without reuse (refresh token rotation)', async () => {
const DUMMY_AUTH_RESULT = { const DUMMY_AUTH_RESULT = {
@ -123,21 +120,18 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
of({ keys: [] } as JwtKeys) of({ keys: [] } as JwtKeys)
); );
service await lastValueFrom(service
.callbackHistoryAndResetJwtKeys( .callbackHistoryAndResetJwtKeys(
callbackContext, callbackContext,
allConfigs[0]!, allConfigs[0]!,
allConfigs allConfigs
) ));
.subscribe(() => {
expect(storagePersistenceServiceSpy).toBeCalledWith([ expect(storagePersistenceServiceSpy).toBeCalledWith([
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]], ['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
['jwtKeys', { keys: [] }, allConfigs[0]], ['jwtKeys', { keys: [] }, allConfigs[0]],
]); ]);;
// write authnResult & refresh_token & jwtKeys
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2); expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
}); });
});
it('writes refresh_token into the storage with reuse (without refresh token rotation)', async () => { it('writes refresh_token into the storage with reuse (without refresh token rotation)', async () => {
const DUMMY_AUTH_RESULT = { const DUMMY_AUTH_RESULT = {
@ -163,22 +157,19 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue( vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({ keys: [] } as JwtKeys) of({ keys: [] } as JwtKeys)
); );
service await lastValueFrom(service
.callbackHistoryAndResetJwtKeys( .callbackHistoryAndResetJwtKeys(
callbackContext, callbackContext,
allConfigs[0]!, allConfigs[0]!,
allConfigs allConfigs
) ));
.subscribe(() => {
expect(storagePersistenceServiceSpy).toBeCalledWith([ expect(storagePersistenceServiceSpy).toBeCalledWith([
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]], ['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
['reusable_refresh_token', 'dummy_refresh_token', allConfigs[0]], ['reusable_refresh_token', 'dummy_refresh_token', allConfigs[0]],
['jwtKeys', { keys: [] }, allConfigs[0]], ['jwtKeys', { keys: [] }, allConfigs[0]],
]); ]);;
// write authnResult & refresh_token & jwtKeys
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3); expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3);
}); });
});
it('resetBrowserHistory if historyCleanup is turned on and is not in a renewProcess', async () => { it('resetBrowserHistory if historyCleanup is turned on and is not in a renewProcess', async () => {
const DUMMY_AUTH_RESULT = { const DUMMY_AUTH_RESULT = {
@ -200,16 +191,14 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue( vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({ keys: [] } as JwtKeys) of({ keys: [] } as JwtKeys)
); );
service await lastValueFrom(service
.callbackHistoryAndResetJwtKeys( .callbackHistoryAndResetJwtKeys(
callbackContext, callbackContext,
allConfigs[0]!, allConfigs[0]!,
allConfigs allConfigs
) ));
.subscribe(() => {
expect(windowSpy).toHaveBeenCalledTimes(1); expect(windowSpy).toHaveBeenCalledTimes(1);
}); });
});
it('returns callbackContext with jwtkeys filled if everything works fine', async () => { it('returns callbackContext with jwtkeys filled if everything works fine', async () => {
const DUMMY_AUTH_RESULT = { const DUMMY_AUTH_RESULT = {
@ -230,20 +219,18 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue( vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
of({ keys: [{ kty: 'henlo' } as JwtKey] } as JwtKeys) of({ keys: [{ kty: 'henlo' } as JwtKey] } as JwtKeys)
); );
service const result = await lastValueFrom(service
.callbackHistoryAndResetJwtKeys( .callbackHistoryAndResetJwtKeys(
callbackContext, callbackContext,
allConfigs[0]!, allConfigs[0]!,
allConfigs allConfigs
) ));
.subscribe((result) => {
expect(result).toEqual({ expect(result).toEqual({
isRenewProcess: false, isRenewProcess: false,
authResult: DUMMY_AUTH_RESULT, authResult: DUMMY_AUTH_RESULT,
jwtKeys: { keys: [{ kty: 'henlo' }] }, jwtKeys: { keys: [{ kty: 'henlo' }] },
} as CallbackContext); } as CallbackContext);
}); });
});
it('returns error if no jwtKeys have been in the call --> keys are null', async () => { it('returns error if no jwtKeys have been in the call --> keys are null', async () => {
const DUMMY_AUTH_RESULT = { const DUMMY_AUTH_RESULT = {

View File

@ -57,12 +57,10 @@ describe('ImplicitFlowCallbackHandlerService', () => {
}, },
]; ];
service await lastValueFrom(service
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash') .implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash'));
.subscribe(() => {
expect(resetAuthorizationDataSpy).toHaveBeenCalled(); expect(resetAuthorizationDataSpy).toHaveBeenCalled();
}); });
});
it('does NOT calls "resetAuthorizationData" if silent renew is running', async () => { it('does NOT calls "resetAuthorizationData" if silent renew is running', async () => {
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true); vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
@ -76,12 +74,10 @@ describe('ImplicitFlowCallbackHandlerService', () => {
}, },
]; ];
service await lastValueFrom(service
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash') .implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash'));
.subscribe(() => {
expect(resetAuthorizationDataSpy).not.toHaveBeenCalled(); expect(resetAuthorizationDataSpy).not.toHaveBeenCalled();
}); });
});
it('returns callbackContext if all params are good', async () => { it('returns callbackContext if all params are good', async () => {
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true); vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
@ -103,12 +99,10 @@ describe('ImplicitFlowCallbackHandlerService', () => {
}, },
]; ];
service const callbackContext = await lastValueFrom(service
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'anyHash') .implicitFlowCallback(allConfigs[0]!, allConfigs, 'anyHash'));
.subscribe((callbackContext) => {
expect(callbackContext).toEqual(expectedCallbackContext); expect(callbackContext).toEqual(expectedCallbackContext);
}); });
});
it('uses window location hash if no hash is passed', async () => { it('uses window location hash if no hash is passed', async () => {
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true); vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
@ -130,11 +124,9 @@ describe('ImplicitFlowCallbackHandlerService', () => {
}, },
]; ];
service const callbackContext = await lastValueFrom(service
.implicitFlowCallback(allConfigs[0]!, allConfigs) .implicitFlowCallback(allConfigs[0]!, allConfigs));
.subscribe((callbackContext) => {
expect(callbackContext).toEqual(expectedCallbackContext); expect(callbackContext).toEqual(expectedCallbackContext);
}); });
}); });
}); });
});

View File

@ -56,12 +56,10 @@ describe('RefreshSessionCallbackHandlerService', () => {
existingIdToken: 'henlo-legger', existingIdToken: 'henlo-legger',
} as CallbackContext; } as CallbackContext;
service const callbackContext = await lastValueFrom(service
.refreshSessionWithRefreshTokens({ configId: 'configId1' }) .refreshSessionWithRefreshTokens({ configId: 'configId1' }));
.subscribe((callbackContext) => {
expect(callbackContext).toEqual(expectedCallbackContext); expect(callbackContext).toEqual(expectedCallbackContext);
}); });
});
it('throws error if no refresh token is given', async () => { it('throws error if no refresh token is given', async () => {
vi.spyOn( vi.spyOn(

View File

@ -66,25 +66,22 @@ describe('RefreshTokenCallbackHandlerService', () => {
() => ({ tokenEndpoint: 'tokenEndpoint' }) () => ({ tokenEndpoint: 'tokenEndpoint' })
); );
service await lastValueFrom(service
.refreshTokensRequestTokens({} as CallbackContext, { .refreshTokensRequestTokens({} as CallbackContext, {
configId: 'configId1', configId: 'configId1',
}) }));
.subscribe(() => {
expect(postSpy).toHaveBeenCalledExactlyOnceWith( expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'tokenEndpoint', 'tokenEndpoint',
undefined, undefined,
{ configId: 'configId1' }, { configId: 'configId1' },
expect.any(HttpHeaders) expect.any(HttpHeaders)
); );;
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders; const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
expect(httpHeaders.has('Content-Type')).toBeTruthy();;
expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe( expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded' 'application/x-www-form-urlencoded'
); );
}); });
});
it('calls data service with correct headers if all params are good', async () => { it('calls data service with correct headers if all params are good', async () => {
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({})); const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
@ -95,19 +92,16 @@ describe('RefreshTokenCallbackHandlerService', () => {
() => ({ tokenEndpoint: 'tokenEndpoint' }) () => ({ tokenEndpoint: 'tokenEndpoint' })
); );
service await lastValueFrom(service
.refreshTokensRequestTokens({} as CallbackContext, { .refreshTokensRequestTokens({} as CallbackContext, {
configId: 'configId1', configId: 'configId1',
}) }));
.subscribe(() => { const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders; expect(httpHeaders.has('Content-Type')).toBeTruthy();;
expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe( expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded' 'application/x-www-form-urlencoded'
); );
}); });
});
it('returns error in case of http error', async () => { it('returns error in case of http error', async () => {
vi.spyOn(dataService, 'post').mockReturnValue( vi.spyOn(dataService, 'post').mockReturnValue(

View File

@ -69,13 +69,12 @@ describe('StateValidationCallbackHandlerService', () => {
); );
const allConfigs = [{ configId: 'configId1' }]; const allConfigs = [{ configId: 'configId1' }];
service const newCallbackContext = await lastValueFrom(service
.callbackStateValidation( .callbackStateValidation(
{} as CallbackContext, {} as CallbackContext,
allConfigs[0]!, allConfigs[0]!,
allConfigs allConfigs
) ));
.subscribe((newCallbackContext) => {
expect(newCallbackContext).toEqual({ expect(newCallbackContext).toEqual({
validationResult: { validationResult: {
idToken: 'idTokenJustForTesting', idToken: 'idTokenJustForTesting',
@ -83,7 +82,6 @@ describe('StateValidationCallbackHandlerService', () => {
}, },
} as CallbackContext); } as CallbackContext);
}); });
});
it('logs error in case of an error', async () => { it('logs error in case of an error', async () => {
vi.spyOn( vi.spyOn(

View File

@ -73,13 +73,11 @@ describe('UserCallbackHandlerService', () => {
const spy = vi.spyOn(flowsDataService, 'setSessionState'); const spy = vi.spyOn(flowsDataService, 'setSessionState');
service const resultCallbackContext = await lastValueFrom(service
.callbackUser(callbackContext, allConfigs[0]!, allConfigs) .callbackUser(callbackContext, allConfigs[0]!, allConfigs));
.subscribe((resultCallbackContext) => { expect(spy).toHaveBeenCalledExactlyOnceWith('mystate', allConfigs[0]);;
expect(spy).toHaveBeenCalledExactlyOnceWith('mystate', allConfigs[0]);
expect(resultCallbackContext).toEqual(callbackContext); expect(resultCallbackContext).toEqual(callbackContext);
}); });
});
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false, isRenewProcess is true and refreshToken is null', async () => { it('does NOT call flowsDataService.setSessionState if autoUserInfo is false, isRenewProcess is true and refreshToken is null', async () => {
const svr = new StateValidationResult( const svr = new StateValidationResult(
@ -107,13 +105,11 @@ describe('UserCallbackHandlerService', () => {
]; ];
const spy = vi.spyOn(flowsDataService, 'setSessionState'); const spy = vi.spyOn(flowsDataService, 'setSessionState');
service const resultCallbackContext = await lastValueFrom(service
.callbackUser(callbackContext, allConfigs[0]!, allConfigs) .callbackUser(callbackContext, allConfigs[0]!, allConfigs));
.subscribe((resultCallbackContext) => { expect(spy).not.toHaveBeenCalled();;
expect(spy).not.toHaveBeenCalled();
expect(resultCallbackContext).toEqual(callbackContext); expect(resultCallbackContext).toEqual(callbackContext);
}); });
});
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value', async () => { it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value', async () => {
const svr = new StateValidationResult( const svr = new StateValidationResult(
@ -141,13 +137,11 @@ describe('UserCallbackHandlerService', () => {
]; ];
const spy = vi.spyOn(flowsDataService, 'setSessionState'); const spy = vi.spyOn(flowsDataService, 'setSessionState');
service const resultCallbackContext = await lastValueFrom(service
.callbackUser(callbackContext, allConfigs[0]!, allConfigs) .callbackUser(callbackContext, allConfigs[0]!, allConfigs));
.subscribe((resultCallbackContext) => { expect(spy).not.toHaveBeenCalled();;
expect(spy).not.toHaveBeenCalled();
expect(resultCallbackContext).toEqual(callbackContext); 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 () => { it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value, id_token is false', async () => {
const svr = new StateValidationResult('accesstoken', '', true, ''); const svr = new StateValidationResult('accesstoken', '', true, '');
@ -171,13 +165,11 @@ describe('UserCallbackHandlerService', () => {
const spy = vi.spyOn(flowsDataService, 'setSessionState'); const spy = vi.spyOn(flowsDataService, 'setSessionState');
service const resultCallbackContext = await lastValueFrom(service
.callbackUser(callbackContext, allConfigs[0]!, allConfigs) .callbackUser(callbackContext, allConfigs[0]!, allConfigs));
.subscribe((resultCallbackContext) => { expect(spy).not.toHaveBeenCalled();;
expect(spy).not.toHaveBeenCalled();
expect(resultCallbackContext).toEqual(callbackContext); expect(resultCallbackContext).toEqual(callbackContext);
}); });
});
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is false', async () => { it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is false', async () => {
const svr = new StateValidationResult( const svr = new StateValidationResult(
@ -210,17 +202,15 @@ describe('UserCallbackHandlerService', () => {
'updateAndPublishAuthState' 'updateAndPublishAuthState'
); );
service const resultCallbackContext = await lastValueFrom(service
.callbackUser(callbackContext, allConfigs[0]!, allConfigs) .callbackUser(callbackContext, allConfigs[0]!, allConfigs));
.subscribe((resultCallbackContext) => {
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({ expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: true, isAuthenticated: true,
validationResult: ValidationResult.NotSet, validationResult: ValidationResult.NotSet,
isRenewProcess: false, isRenewProcess: false,
}); });;
expect(resultCallbackContext).toEqual(callbackContext); expect(resultCallbackContext).toEqual(callbackContext);
}); });
});
it('calls userService.getAndPersistUserDataInStore with correct params if autoUserInfo is true', async () => { it('calls userService.getAndPersistUserDataInStore with correct params if autoUserInfo is true', async () => {
const svr = new StateValidationResult( const svr = new StateValidationResult(
@ -252,9 +242,8 @@ describe('UserCallbackHandlerService', () => {
.spyOn(userService, 'getAndPersistUserDataInStore') .spyOn(userService, 'getAndPersistUserDataInStore')
.mockReturnValue(of({ user: 'some_data' })); .mockReturnValue(of({ user: 'some_data' }));
service const resultCallbackContext = await lastValueFrom(service
.callbackUser(callbackContext, allConfigs[0]!, allConfigs) .callbackUser(callbackContext, allConfigs[0]!, allConfigs));
.subscribe((resultCallbackContext) => {
expect( expect(
getAndPersistUserDataInStoreSpy getAndPersistUserDataInStoreSpy
).toHaveBeenCalledExactlyOnceWith( ).toHaveBeenCalledExactlyOnceWith(
@ -263,10 +252,9 @@ describe('UserCallbackHandlerService', () => {
false, false,
'idtoken', 'idtoken',
'decoded' 'decoded'
); );;
expect(resultCallbackContext).toEqual(callbackContext); expect(resultCallbackContext).toEqual(callbackContext);
}); });
});
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is true', async () => { it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is true', async () => {
const svr = new StateValidationResult( const svr = new StateValidationResult(
@ -303,17 +291,15 @@ describe('UserCallbackHandlerService', () => {
'updateAndPublishAuthState' 'updateAndPublishAuthState'
); );
service const resultCallbackContext = await lastValueFrom(service
.callbackUser(callbackContext, allConfigs[0]!, allConfigs) .callbackUser(callbackContext, allConfigs[0]!, allConfigs));
.subscribe((resultCallbackContext) => {
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({ expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
isAuthenticated: true, isAuthenticated: true,
validationResult: ValidationResult.MaxOffsetExpired, validationResult: ValidationResult.MaxOffsetExpired,
isRenewProcess: false, isRenewProcess: false,
}); });;
expect(resultCallbackContext).toEqual(callbackContext); expect(resultCallbackContext).toEqual(callbackContext);
}); });
});
it('calls flowsDataService.setSessionState with correct params if user data is present and NOT refresh token', async () => { it('calls flowsDataService.setSessionState with correct params if user data is present and NOT refresh token', async () => {
const svr = new StateValidationResult( const svr = new StateValidationResult(
@ -347,16 +333,14 @@ describe('UserCallbackHandlerService', () => {
); );
const setSessionStateSpy = vi.spyOn(flowsDataService, 'setSessionState'); const setSessionStateSpy = vi.spyOn(flowsDataService, 'setSessionState');
service const resultCallbackContext = await lastValueFrom(service
.callbackUser(callbackContext, allConfigs[0]!, allConfigs) .callbackUser(callbackContext, allConfigs[0]!, allConfigs));
.subscribe((resultCallbackContext) => {
expect(setSessionStateSpy).toHaveBeenCalledExactlyOnceWith( expect(setSessionStateSpy).toHaveBeenCalledExactlyOnceWith(
'mystate', 'mystate',
allConfigs[0] allConfigs[0]
); );;
expect(resultCallbackContext).toEqual(callbackContext); expect(resultCallbackContext).toEqual(callbackContext);
}); });
});
it('calls authStateService.publishUnauthorizedState with correct params if user info which are coming back are null', async () => { it('calls authStateService.publishUnauthorizedState with correct params if user info which are coming back are null', async () => {
const svr = new StateValidationResult( const svr = new StateValidationResult(

View File

@ -90,21 +90,19 @@ describe('Flows Service', () => {
}, },
]; ];
service const value = await lastValueFrom(service
.processCodeFlowCallback('some-url1234', allConfigs[0]!, allConfigs) .processCodeFlowCallback('some-url1234', allConfigs[0]!, allConfigs));
.subscribe((value) => { expect(value).toEqual({} as CallbackContext);;
expect(value).toEqual({} as CallbackContext);
expect(codeFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith( expect(codeFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith(
'some-url1234', 'some-url1234',
allConfigs[0] allConfigs[0]
); );;
expect(codeFlowCodeRequestSpy).toHaveBeenCalledTimes(1); expect(codeFlowCodeRequestSpy).toHaveBeenCalledTimes(1);;
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalledTimes(1); expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalledTimes(1);;
expect(callbackStateValidationSpy).toHaveBeenCalledTimes(1); expect(callbackStateValidationSpy).toHaveBeenCalledTimes(1);;
expect(callbackUserSpy).toHaveBeenCalledTimes(1); expect(callbackUserSpy).toHaveBeenCalledTimes(1);
}); });
}); });
});
describe('processSilentRenewCodeFlowCallback', () => { describe('processSilentRenewCodeFlowCallback', () => {
it('calls all methods correctly', async () => { it('calls all methods correctly', async () => {
@ -129,21 +127,19 @@ describe('Flows Service', () => {
}, },
]; ];
service const value = await lastValueFrom(service
.processSilentRenewCodeFlowCallback( .processSilentRenewCodeFlowCallback(
{} as CallbackContext, {} as CallbackContext,
allConfigs[0]!, allConfigs[0]!,
allConfigs allConfigs
) ));
.subscribe((value) => { expect(value).toEqual({} as CallbackContext);;
expect(value).toEqual({} as CallbackContext); expect(codeFlowCodeRequestSpy).toHaveBeenCalled();;
expect(codeFlowCodeRequestSpy).toHaveBeenCalled(); expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();;
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled(); expect(callbackStateValidationSpy).toHaveBeenCalled();;
expect(callbackStateValidationSpy).toHaveBeenCalled();
expect(callbackUserSpy).toHaveBeenCalled(); expect(callbackUserSpy).toHaveBeenCalled();
}); });
}); });
});
describe('processImplicitFlowCallback', () => { describe('processImplicitFlowCallback', () => {
it('calls all methods correctly', async () => { it('calls all methods correctly', async () => {
@ -168,17 +164,15 @@ describe('Flows Service', () => {
}, },
]; ];
service const value = await lastValueFrom(service
.processImplicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash') .processImplicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash'));
.subscribe((value) => { expect(value).toEqual({} as CallbackContext);;
expect(value).toEqual({} as CallbackContext); expect(implicitFlowCallbackSpy).toHaveBeenCalled();;
expect(implicitFlowCallbackSpy).toHaveBeenCalled(); expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();;
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled(); expect(callbackStateValidationSpy).toHaveBeenCalled();;
expect(callbackStateValidationSpy).toHaveBeenCalled();
expect(callbackUserSpy).toHaveBeenCalled(); expect(callbackUserSpy).toHaveBeenCalled();
}); });
}); });
});
describe('processRefreshToken', () => { describe('processRefreshToken', () => {
it('calls all methods correctly', async () => { it('calls all methods correctly', async () => {
@ -209,16 +203,14 @@ describe('Flows Service', () => {
}, },
]; ];
service const value = await lastValueFrom(service
.processRefreshToken(allConfigs[0]!, allConfigs) .processRefreshToken(allConfigs[0]!, allConfigs));
.subscribe((value) => { expect(value).toEqual({} as CallbackContext);;
expect(value).toEqual({} as CallbackContext); expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();;
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled(); expect(refreshTokensRequestTokensSpy).toHaveBeenCalled();;
expect(refreshTokensRequestTokensSpy).toHaveBeenCalled(); expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled();;
expect(callbackHistoryAndResetJwtKeysSpy).toHaveBeenCalled(); expect(callbackStateValidationSpy).toHaveBeenCalled();;
expect(callbackStateValidationSpy).toHaveBeenCalled();
expect(callbackUserSpy).toHaveBeenCalled(); expect(callbackUserSpy).toHaveBeenCalled();
}); });
}); });
}); });
});

View File

@ -1,4 +1,9 @@
import type { HttpFeature } from '@ngify/http'; import type { HttpFeature, HttpInterceptor } from '@ngify/http';
import { InjectionToken } from 'injection-js';
export const HTTP_INTERCEPTORS = new InjectionToken<readonly HttpInterceptor[]>(
'HTTP_INTERCEPTORS'
);
export function provideHttpClient() { export function provideHttpClient() {
// todo // todo

View File

@ -320,11 +320,10 @@ describe('CheckSessionService', () => {
serviceAsAny.lastIFrameRefresh = lastRefresh; serviceAsAny.lastIFrameRefresh = lastRefresh;
serviceAsAny.iframeRefreshInterval = lastRefresh; serviceAsAny.iframeRefreshInterval = lastRefresh;
serviceAsAny.init().subscribe((result: any) => { const result = await lastValueFrom(serviceAsAny.init());
expect(result).toBeUndefined(); expect(result).toBeUndefined();
}); });
}); });
});
describe('isCheckSessionConfigured', () => { describe('isCheckSessionConfigured', () => {
it('returns true if startCheckSession on config is true', () => { it('returns true if startCheckSession on config is true', () => {
@ -364,10 +363,9 @@ expect(result).toBe(false);
const expectedResultsInOrder = [false, true]; const expectedResultsInOrder = [false, true];
let counter = 0; let counter = 0;
checkSessionService.checkSessionChanged$.subscribe((result) => { const result = await lastValueFrom(checkSessionService.checkSessionChanged$);
expect(result).toBe(expectedResultsInOrder[counter]); expect(result).toBe(expectedResultsInOrder[counter]);;
counter++; counter++;
});
(checkSessionService as any).checkSessionChangedInternal$.next(true); (checkSessionService as any).checkSessionChangedInternal$.next(true);
}); });

View File

@ -41,9 +41,8 @@ describe('RefreshSessionIframeService ', () => {
.mockReturnValue(of(null)); .mockReturnValue(of(null));
const allConfigs = [{ configId: 'configId1' }]; const allConfigs = [{ configId: 'configId1' }];
refreshSessionIframeService await lastValueFrom(refreshSessionIframeService
.refreshSessionWithIframe(allConfigs[0]!, allConfigs) .refreshSessionWithIframe(allConfigs[0]!, allConfigs));
.subscribe(() => {
expect( expect(
sendAuthorizeRequestUsingSilentRenewSpy sendAuthorizeRequestUsingSilentRenewSpy
).toHaveBeenCalledExactlyOnceWith( ).toHaveBeenCalledExactlyOnceWith(
@ -53,7 +52,6 @@ describe('RefreshSessionIframeService ', () => {
); );
}); });
}); });
});
describe('initSilentRenewRequest', () => { describe('initSilentRenewRequest', () => {
it('dispatches customevent to window object', async () => { it('dispatches customevent to window object', async () => {

View File

@ -152,16 +152,14 @@ describe('SilentRenewService ', () => {
const urlParts = const urlParts =
'code=some-code&state=some-state&session_state=some-session-state'; 'code=some-code&state=some-state&session_state=some-session-state';
silentRenewService await lastValueFrom(silentRenewService
.codeFlowCallbackSilentRenewIframe([url, urlParts], config, allConfigs) .codeFlowCallbackSilentRenewIframe([url, urlParts], config, allConfigs));
.subscribe(() => {
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(
expectedContext, expectedContext,
config, config,
allConfigs allConfigs
); );
}); });
});
it('throws error if url has error param and resets everything on error', async () => { it('throws error if url has error param and resets everything on error', async () => {
const config = { configId: 'configId1' }; const config = { configId: 'configId1' };
@ -308,13 +306,10 @@ describe('SilentRenewService ', () => {
const eventData = { detail: 'detail?detail2' } as CustomEvent; const eventData = { detail: 'detail?detail2' } as CustomEvent;
const allConfigs = [{ configId: 'configId1' }]; const allConfigs = [{ configId: 'configId1' }];
silentRenewService.refreshSessionWithIFrameCompleted$.subscribe( const result = await lastValueFrom(silentRenewService.refreshSessionWithIFrameCompleted$);
(result) => {
expect(result).toEqual({ expect(result).toEqual({
refreshToken: 'callbackContext', refreshToken: 'callbackContext',
} as CallbackContext); } as CallbackContext);
}
);
silentRenewService.silentRenewEventHandler( silentRenewService.silentRenewEventHandler(
eventData, eventData,
@ -357,11 +352,8 @@ describe('SilentRenewService ', () => {
const eventData = { detail: 'detail?detail2' } as CustomEvent; const eventData = { detail: 'detail?detail2' } as CustomEvent;
const allConfigs = [{ configId: 'configId1' }]; const allConfigs = [{ configId: 'configId1' }];
silentRenewService.refreshSessionWithIFrameCompleted$.subscribe( const result = await lastValueFrom(silentRenewService.refreshSessionWithIFrameCompleted$);
(result) => {
expect(result).toBeNull(); expect(result).toBeNull();
}
);
silentRenewService.silentRenewEventHandler( silentRenewService.silentRenewEventHandler(
eventData, eventData,

View File

@ -30,3 +30,4 @@ export * from './validation/state-validation-result';
export * from './validation/validation-result'; export * from './validation/validation-result';
export * from './injection'; export * from './injection';
export * from './router'; export * from './router';
export * from './http';

View File

@ -103,9 +103,8 @@ describe(`AuthHttpInterceptor`, () => {
true true
); );
httpClient.get(actionUrl).subscribe((response) => { const response = await lastValueFrom(httpClient.get(actionUrl));
expect(response).toBeTruthy(); expect(response).toBeTruthy();
});
const httpRequest = httpTestingController.expectOne(actionUrl); const httpRequest = httpTestingController.expectOne(actionUrl);
@ -130,9 +129,8 @@ describe(`AuthHttpInterceptor`, () => {
true true
); );
httpClient.get(actionUrl).subscribe((response) => { const response = await lastValueFrom(httpClient.get(actionUrl));
expect(response).toBeTruthy(); expect(response).toBeTruthy();
});
const httpRequest = httpTestingController.expectOne(actionUrl); const httpRequest = httpTestingController.expectOne(actionUrl);
@ -159,9 +157,8 @@ describe(`AuthHttpInterceptor`, () => {
'thisIsAToken' 'thisIsAToken'
); );
httpClient.get(actionUrl).subscribe((response) => { const response = await lastValueFrom(httpClient.get(actionUrl));
expect(response).toBeTruthy(); expect(response).toBeTruthy();
});
const httpRequest = httpTestingController.expectOne(actionUrl); const httpRequest = httpTestingController.expectOne(actionUrl);
@ -185,9 +182,8 @@ describe(`AuthHttpInterceptor`, () => {
true true
); );
httpClient.get(actionUrl).subscribe((response) => { const response = await lastValueFrom(httpClient.get(actionUrl));
expect(response).toBeTruthy(); expect(response).toBeTruthy();
});
const httpRequest = httpTestingController.expectOne(actionUrl); const httpRequest = httpTestingController.expectOne(actionUrl);
@ -212,9 +208,8 @@ describe(`AuthHttpInterceptor`, () => {
); );
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(''); vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('');
httpClient.get(actionUrl).subscribe((response) => { const response = await lastValueFrom(httpClient.get(actionUrl));
expect(response).toBeTruthy(); expect(response).toBeTruthy();
});
const httpRequest = httpTestingController.expectOne(actionUrl); const httpRequest = httpTestingController.expectOne(actionUrl);
@ -231,9 +226,8 @@ describe(`AuthHttpInterceptor`, () => {
false false
); );
httpClient.get(actionUrl).subscribe((response) => { const response = await lastValueFrom(httpClient.get(actionUrl));
expect(response).toBeTruthy(); expect(response).toBeTruthy();
});
const httpRequest = httpTestingController.expectOne(actionUrl); const httpRequest = httpTestingController.expectOne(actionUrl);
@ -263,9 +257,8 @@ describe(`AuthHttpInterceptor`, () => {
matchingConfig: null, matchingConfig: null,
}); });
httpClient.get(actionUrl).subscribe((response) => { const response = await lastValueFrom(httpClient.get(actionUrl));
expect(response).toBeTruthy(); expect(response).toBeTruthy();
});
const httpRequest = httpTestingController.expectOne(actionUrl); const httpRequest = httpTestingController.expectOne(actionUrl);
@ -290,13 +283,11 @@ describe(`AuthHttpInterceptor`, () => {
true true
); );
httpClient.get(actionUrl).subscribe((response) => { const response = await lastValueFrom(httpClient.get(actionUrl));
expect(response).toBeTruthy(); expect(response).toBeTruthy();
});
httpClient.get(actionUrl2).subscribe((response) => { const response = await lastValueFrom(httpClient.get(actionUrl2));
expect(response).toBeTruthy(); expect(response).toBeTruthy();
});
const httpRequest = httpTestingController.expectOne(actionUrl); const httpRequest = httpTestingController.expectOne(actionUrl);

View File

@ -1,4 +1,4 @@
import { import type {
HttpEvent, HttpEvent,
HttpHandler, HttpHandler,
HttpHandlerFn, HttpHandlerFn,
@ -6,8 +6,8 @@ import {
HttpInterceptorFn, HttpInterceptorFn,
HttpRequest, HttpRequest,
} from '@ngify/http'; } from '@ngify/http';
import { inject, Injectable } from 'injection-js'; import { Injectable, inject } from 'injection-js';
import { Observable } from 'rxjs'; import type { Observable } from 'rxjs';
import { AuthStateService } from '../auth-state/auth-state.service'; import { AuthStateService } from '../auth-state/auth-state.service';
import { ConfigurationService } from '../config/config.service'; import { ConfigurationService } from '../config/config.service';
import { LoggerService } from '../logging/logger.service'; import { LoggerService } from '../logging/logger.service';

View File

@ -118,12 +118,10 @@ describe('LoginService', () => {
.mockReturnValue(of({} as LoginResponse)); .mockReturnValue(of({} as LoginResponse));
// act // act
service.loginWithPopUp(config, [config]).subscribe(() => { await lastValueFrom(service.loginWithPopUp(config, [config]));
// assert expect(loginWithPopUpPar).toHaveBeenCalledTimes(1);;
expect(loginWithPopUpPar).toHaveBeenCalledTimes(1);
expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled(); expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled();
}); });
});
it('calls standardLoginService loginstandard if usePushedAuthorisationRequests is false', async () => { it('calls standardLoginService loginstandard if usePushedAuthorisationRequests is false', async () => {
// arrange // arrange
@ -136,12 +134,10 @@ describe('LoginService', () => {
.mockReturnValue(of({} as LoginResponse)); .mockReturnValue(of({} as LoginResponse));
// act // act
service.loginWithPopUp(config, [config]).subscribe(() => { await lastValueFrom(service.loginWithPopUp(config, [config]));
// assert expect(loginWithPopUpPar).not.toHaveBeenCalled();;
expect(loginWithPopUpPar).not.toHaveBeenCalled();
expect(loginWithPopUpStandardSpy).toHaveBeenCalledTimes(1); expect(loginWithPopUpStandardSpy).toHaveBeenCalledTimes(1);
}); });
});
it('stores the customParams to the storage if customParams are given', async () => { it('stores the customParams to the storage if customParams are given', async () => {
// arrange // arrange
@ -157,15 +153,13 @@ describe('LoginService', () => {
); );
// act // act
service.loginWithPopUp(config, [config], authOptions).subscribe(() => { await lastValueFrom(service.loginWithPopUp(config, [config], authOptions));
// assert
expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith( expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
'storageCustomParamsAuthRequest', 'storageCustomParamsAuthRequest',
{ custom: 'params' }, { custom: 'params' },
config config
); );
}); });
});
it('returns error if there is already a popup open', () => { it('returns error if there is already a popup open', () => {
// arrange // arrange
@ -181,16 +175,13 @@ describe('LoginService', () => {
vi.spyOn(popUpService, 'isCurrentlyInPopup').mockReturnValue(true); vi.spyOn(popUpService, 'isCurrentlyInPopup').mockReturnValue(true);
// act // act
service const result = await lastValueFrom(service
.loginWithPopUp(config, [config], authOptions) .loginWithPopUp(config, [config], authOptions));
.subscribe((result) => {
// assert
expect(result).toEqual({ expect(result).toEqual({
errorMessage: 'There is already a popup open.', errorMessage: 'There is already a popup open.',
} as LoginResponse); } as LoginResponse);;
expect(loginWithPopUpPar).not.toHaveBeenCalled(); expect(loginWithPopUpPar).not.toHaveBeenCalled();;
expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled(); expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled();
}); });
}); });
}); });
});

View File

@ -368,14 +368,13 @@ describe('ParLoginService', () => {
); );
const spy = vi.spyOn(popupService, 'openPopUp'); const spy = vi.spyOn(popupService, 'openPopUp');
service.loginWithPopUpPar(config, allConfigs).subscribe(() => { await lastValueFrom(service.loginWithPopUpPar(config, allConfigs));
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(
'some-par-url', 'some-par-url',
undefined, undefined,
config config
); );
}); });
});
it('returns correct properties if URL is received', async () => { it('returns correct properties if URL is received', async () => {
vi.spyOn( vi.spyOn(
@ -419,13 +418,12 @@ describe('ParLoginService', () => {
spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult)); spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
service.loginWithPopUpPar(config, allConfigs).subscribe((result) => { const result = await lastValueFrom(service.loginWithPopUpPar(config, allConfigs));
expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith( expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
allConfigs, allConfigs,
'someUrl' 'someUrl'
); );;
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: true, isAuthenticated: true,
configId: 'configId1', configId: 'configId1',
@ -434,7 +432,6 @@ describe('ParLoginService', () => {
accessToken: 'anyAccessToken', accessToken: 'anyAccessToken',
}); });
}); });
});
it('returns correct properties if popup was closed by user', async () => { it('returns correct properties if popup was closed by user', async () => {
vi.spyOn( vi.spyOn(
@ -465,8 +462,8 @@ describe('ParLoginService', () => {
spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult)); spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
service.loginWithPopUpPar(config, allConfigs).subscribe((result) => { const result = await lastValueFrom(service.loginWithPopUpPar(config, allConfigs));
expect(checkAuthSpy).not.toHaveBeenCalled(); expect(checkAuthSpy).not.toHaveBeenCalled();;
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: false, isAuthenticated: false,
errorMessage: 'User closed popup', errorMessage: 'User closed popup',
@ -478,4 +475,3 @@ describe('ParLoginService', () => {
}); });
}); });
}); });
});

View File

@ -91,7 +91,7 @@ describe('ParService', () => {
.spyOn(dataService, 'post') .spyOn(dataService, 'post')
.mockReturnValue(of({})); .mockReturnValue(of({}));
service.postParRequest({ configId: 'configId1' }).subscribe(() => { await lastValueFrom(service.postParRequest({ configId: 'configId1' }));
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith( expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
'parEndpoint', 'parEndpoint',
'some-url123', 'some-url123',
@ -99,7 +99,6 @@ describe('ParService', () => {
expect.any(HttpHeaders) expect.any(HttpHeaders)
); );
}); });
});
it('Gives back correct object properties', async () => { it('Gives back correct object properties', async () => {
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue( vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
@ -113,10 +112,9 @@ describe('ParService', () => {
vi.spyOn(dataService, 'post').mockReturnValue( vi.spyOn(dataService, 'post').mockReturnValue(
of({ expires_in: 123, request_uri: 'request_uri' }) of({ expires_in: 123, request_uri: 'request_uri' })
); );
service.postParRequest({ configId: 'configId1' }).subscribe((result) => { const result = await lastValueFrom(service.postParRequest({ configId: 'configId1' }));
expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' }); expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
}); });
});
it('throws error if data service has got an error', async () => { it('throws error if data service has got an error', async () => {
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue( vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(

View File

@ -1,6 +1,5 @@
import { TestBed } from '@/testing'; import { TestBed, spyOnProperty } from '@/testing';
import { CommonModule } from '@angular/common'; import { lastValueFrom, of } from 'rxjs';
import { of } from 'rxjs';
import { vi } from 'vitest'; import { vi } from 'vitest';
import { CheckAuthService } from '../../auth-state/check-auth.service'; import { CheckAuthService } from '../../auth-state/check-auth.service';
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service'; import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
@ -24,7 +23,7 @@ describe('PopUpLoginService', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CommonModule], imports: [],
providers: [ providers: [
PopUpLoginService, PopUpLoginService,
mockProvider(LoggerService), mockProvider(LoggerService),
@ -35,9 +34,6 @@ describe('PopUpLoginService', () => {
mockProvider(CheckAuthService), mockProvider(CheckAuthService),
], ],
}); });
});
beforeEach(() => {
popUpLoginService = TestBed.inject(PopUpLoginService); popUpLoginService = TestBed.inject(PopUpLoginService);
urlService = TestBed.inject(UrlService); urlService = TestBed.inject(UrlService);
loggerService = TestBed.inject(LoggerService); loggerService = TestBed.inject(LoggerService);
@ -93,12 +89,11 @@ describe('PopUpLoginService', () => {
of({} as LoginResponse) of({} as LoginResponse)
); );
popUpLoginService await lastValueFrom(
.loginWithPopUpStandard(config, [config]) popUpLoginService.loginWithPopUpStandard(config, [config])
.subscribe(() => { );
expect(urlService.getAuthorizeUrl).toHaveBeenCalled(); expect(urlService.getAuthorizeUrl).toHaveBeenCalled();
}); });
});
it('opens popup if everything fits', async () => { it('opens popup if everything fits', async () => {
const config = { const config = {
@ -123,12 +118,11 @@ describe('PopUpLoginService', () => {
); );
const popupSpy = vi.spyOn(popupService, 'openPopUp'); const popupSpy = vi.spyOn(popupService, 'openPopUp');
popUpLoginService await lastValueFrom(
.loginWithPopUpStandard(config, [config]) popUpLoginService.loginWithPopUpStandard(config, [config])
.subscribe(() => { );
expect(popupSpy).toHaveBeenCalled(); expect(popupSpy).toHaveBeenCalled();
}); });
});
it('returns three properties when popupservice received an url', async () => { it('returns three properties when popupservice received an url', async () => {
const config = { const config = {
@ -164,15 +158,14 @@ describe('PopUpLoginService', () => {
spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult)); spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
popUpLoginService const result = await lastValueFrom(
.loginWithPopUpStandard(config, [config]) popUpLoginService.loginWithPopUpStandard(config, [config])
.subscribe((result) => { );
expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith( expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
[config], [config],
'someUrl' 'someUrl'
); );
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: true, isAuthenticated: true,
configId: 'configId1', configId: 'configId1',
@ -181,7 +174,6 @@ describe('PopUpLoginService', () => {
accessToken: 'anyAccessToken', accessToken: 'anyAccessToken',
}); });
}); });
});
it('returns two properties if popup was closed by user', async () => { it('returns two properties if popup was closed by user', async () => {
const config = { const config = {
@ -207,9 +199,9 @@ describe('PopUpLoginService', () => {
spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult)); spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
popUpLoginService const result = await lastValueFrom(
.loginWithPopUpStandard(config, [config]) popUpLoginService.loginWithPopUpStandard(config, [config])
.subscribe((result) => { );
expect(checkAuthSpy).not.toHaveBeenCalled(); expect(checkAuthSpy).not.toHaveBeenCalled();
expect(result).toEqual({ expect(result).toEqual({
isAuthenticated: false, isAuthenticated: false,
@ -222,4 +214,3 @@ describe('PopUpLoginService', () => {
}); });
}); });
}); });
});

View File

@ -112,9 +112,8 @@ describe('PopUpService', () => {
receivedUrl: 'some-url1111', receivedUrl: 'some-url1111',
}; };
popUpService.result$.subscribe((result) => { const result = await lastValueFrom(popUpService.result$);
expect(result).toBe(popupResult); expect(result).toBe(popupResult);
});
(popUpService as any).resultInternal$.next(popupResult); (popUpService as any).resultInternal$.next(popupResult);
}); });
@ -195,7 +194,8 @@ describe('PopUpService', () => {
popupResult = {} as PopupResult; popupResult = {} as PopupResult;
popUpService.result$.subscribe((result) => (popupResult = result)); const result = await lastValueFrom(popUpService.result$);
(popupResult = result)
}); });
it('message received with data', async () => { it('message received with data', async () => {

View File

@ -123,12 +123,10 @@ describe('Logout and Revoke Service', () => {
const config = { configId: 'configId1' }; const config = { configId: 'configId1' };
// Act // Act
service.revokeAccessToken(config).subscribe((result) => { const result = await lastValueFrom(service.revokeAccessToken(config));
// Assert expect(result).toEqual({ data: 'anything' });;
expect(result).toEqual({ data: 'anything' });
expect(loggerSpy).toHaveBeenCalled(); expect(loggerSpy).toHaveBeenCalled();
}); });
});
it('loggs error when request is negative', async () => { it('loggs error when request is negative', async () => {
// Arrange // Arrange
@ -310,12 +308,10 @@ describe('Logout and Revoke Service', () => {
const config = { configId: 'configId1' }; const config = { configId: 'configId1' };
// Act // Act
service.revokeRefreshToken(config).subscribe((result) => { const result = await lastValueFrom(service.revokeRefreshToken(config));
// Assert expect(result).toEqual({ data: 'anything' });;
expect(result).toEqual({ data: 'anything' });
expect(loggerSpy).toHaveBeenCalled(); expect(loggerSpy).toHaveBeenCalled();
}); });
});
it('loggs error when request is negative', async () => { it('loggs error when request is negative', async () => {
// Arrange // Arrange
@ -442,10 +438,9 @@ describe('Logout and Revoke Service', () => {
const result$ = service.logoff(config, [config]); const result$ = service.logoff(config, [config]);
// Assert // Assert
result$.subscribe(() => { await lastValueFrom(result$);
expect(serverStateChangedSpy).not.toHaveBeenCalled(); expect(serverStateChangedSpy).not.toHaveBeenCalled();
}); });
});
it('logs and returns if `serverStateChanged` is true', async () => { it('logs and returns if `serverStateChanged` is true', async () => {
// Arrange // Arrange
@ -459,10 +454,9 @@ describe('Logout and Revoke Service', () => {
const result$ = service.logoff(config, [config]); const result$ = service.logoff(config, [config]);
// Assert // Assert
result$.subscribe(() => { await lastValueFrom(result$);
expect(redirectSpy).not.toHaveBeenCalled(); expect(redirectSpy).not.toHaveBeenCalled();
}); });
});
it('calls urlHandler if urlhandler is passed', async () => { it('calls urlHandler if urlhandler is passed', async () => {
// Arrange // Arrange
@ -486,12 +480,11 @@ describe('Logout and Revoke Service', () => {
const result$ = service.logoff(config, [config], { urlHandler }); const result$ = service.logoff(config, [config], { urlHandler });
// Assert // Assert
result$.subscribe(() => { await lastValueFrom(result$);
expect(redirectSpy).not.toHaveBeenCalled(); expect(redirectSpy).not.toHaveBeenCalled();;
expect(spy).toHaveBeenCalledExactlyOnceWith('someValue'); expect(spy).toHaveBeenCalledExactlyOnceWith('someValue');;
expect(resetAuthorizationDataSpy).toHaveBeenCalled(); expect(resetAuthorizationDataSpy).toHaveBeenCalled();
}); });
});
it('calls redirect service if no logoutOptions are passed', async () => { it('calls redirect service if no logoutOptions are passed', async () => {
// Arrange // Arrange
@ -508,10 +501,9 @@ describe('Logout and Revoke Service', () => {
const result$ = service.logoff(config, [config]); const result$ = service.logoff(config, [config]);
// Assert // Assert
result$.subscribe(() => { await lastValueFrom(result$);
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue'); expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
}); });
});
it('calls redirect service if logoutOptions are passed and method is GET', async () => { it('calls redirect service if logoutOptions are passed and method is GET', async () => {
// Arrange // Arrange
@ -528,10 +520,9 @@ describe('Logout and Revoke Service', () => {
const result$ = service.logoff(config, [config], { logoffMethod: 'GET' }); const result$ = service.logoff(config, [config], { logoffMethod: 'GET' });
// Assert // Assert
result$.subscribe(() => { await lastValueFrom(result$);
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue'); expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
}); });
});
it('calls dataservice post if logoutOptions are passed and method is POST', async () => { it('calls dataservice post if logoutOptions are passed and method is POST', async () => {
// Arrange // Arrange
@ -561,8 +552,8 @@ describe('Logout and Revoke Service', () => {
}); });
// Assert // Assert
result$.subscribe(() => { await lastValueFrom(result$);
expect(redirectSpy).not.toHaveBeenCalled(); expect(redirectSpy).not.toHaveBeenCalled();;
expect(postSpy).toHaveBeenCalledExactlyOnceWith( expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'some-url', 'some-url',
{ {
@ -572,16 +563,13 @@ describe('Logout and Revoke Service', () => {
}, },
config, config,
expect.anything() expect.anything()
); );;
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders; expect(httpHeaders.has('Content-Type')).toBeTruthy();;
expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe( expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded' 'application/x-www-form-urlencoded'
); );
}); });
});
it('calls dataservice post if logoutOptions with customParams are passed and method is POST', async () => { it('calls dataservice post if logoutOptions with customParams are passed and method is POST', async () => {
// Arrange // Arrange
@ -616,8 +604,8 @@ describe('Logout and Revoke Service', () => {
}); });
// Assert // Assert
result$.subscribe(() => { await lastValueFrom(result$);
expect(redirectSpy).not.toHaveBeenCalled(); expect(redirectSpy).not.toHaveBeenCalled();;
expect(postSpy).toHaveBeenCalledExactlyOnceWith( expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'some-url', 'some-url',
{ {
@ -630,17 +618,14 @@ describe('Logout and Revoke Service', () => {
}, },
config, config,
expect.anything() expect.anything()
); );;
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders; expect(httpHeaders.has('Content-Type')).toBeTruthy();;
expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe( expect(httpHeaders.get('Content-Type')).toBe(
'application/x-www-form-urlencoded' 'application/x-www-form-urlencoded'
); );
}); });
}); });
});
describe('logoffLocal', () => { describe('logoffLocal', () => {
it('calls flowsService.resetAuthorizationData', () => { it('calls flowsService.resetAuthorizationData', () => {
@ -681,12 +666,10 @@ describe('Logout and Revoke Service', () => {
.mockReturnValue(of({ any: 'thing' })); .mockReturnValue(of({ any: 'thing' }));
// Act // Act
service.logoffAndRevokeTokens(config, [config]).subscribe(() => { await lastValueFrom(service.logoffAndRevokeTokens(config, [config]));
// Assert expect(revokeRefreshTokenSpy).toHaveBeenCalled();;
expect(revokeRefreshTokenSpy).toHaveBeenCalled();
expect(revokeAccessTokenSpy).toHaveBeenCalled(); expect(revokeAccessTokenSpy).toHaveBeenCalled();
}); });
});
it('logs error when revokeaccesstoken throws an error', async () => { it('logs error when revokeaccesstoken throws an error', async () => {
// Arrange // Arrange
@ -736,11 +719,9 @@ describe('Logout and Revoke Service', () => {
const config = { configId: 'configId1' }; const config = { configId: 'configId1' };
// Act // Act
service.logoffAndRevokeTokens(config, [config]).subscribe(() => { await lastValueFrom(service.logoffAndRevokeTokens(config, [config]));
// Assert
expect(logoffSpy).toHaveBeenCalled(); expect(logoffSpy).toHaveBeenCalled();
}); });
});
it('calls logoff with urlhandler in case of success', async () => { it('calls logoff with urlhandler in case of success', async () => {
// Arrange // Arrange
@ -760,15 +741,12 @@ describe('Logout and Revoke Service', () => {
const config = { configId: 'configId1' }; const config = { configId: 'configId1' };
// Act // Act
service await lastValueFrom(service
.logoffAndRevokeTokens(config, [config], { urlHandler }) .logoffAndRevokeTokens(config, [config], { urlHandler }));
.subscribe(() => {
// Assert
expect(logoffSpy).toHaveBeenCalledExactlyOnceWith(config, [config], { expect(logoffSpy).toHaveBeenCalledExactlyOnceWith(config, [config], {
urlHandler, urlHandler,
}); });
}); });
});
it('calls revokeAccessToken when storage does not hold a refreshtoken', async () => { it('calls revokeAccessToken when storage does not hold a refreshtoken', async () => {
// Arrange // Arrange
@ -789,12 +767,10 @@ describe('Logout and Revoke Service', () => {
.mockReturnValue(of({ any: 'thing' })); .mockReturnValue(of({ any: 'thing' }));
// Act // Act
service.logoffAndRevokeTokens(config, [config]).subscribe(() => { await lastValueFrom(service.logoffAndRevokeTokens(config, [config]));
// Assert expect(revokeRefreshTokenSpy).not.toHaveBeenCalled();;
expect(revokeRefreshTokenSpy).not.toHaveBeenCalled();
expect(revokeAccessTokenSpy).toHaveBeenCalled(); expect(revokeAccessTokenSpy).toHaveBeenCalled();
}); });
});
it('logs error when revokeaccesstoken throws an error', async () => { it('logs error when revokeaccesstoken throws an error', async () => {
// Arrange // Arrange

View File

@ -225,11 +225,10 @@ describe('OidcSecurityService', () => {
some: 'thing', some: 'thing',
}); });
oidcSecurityService.getUserData('configId').subscribe((result) => { const result = await lastValueFrom(oidcSecurityService.getUserData('configId'));
expect(result).toEqual({ some: 'thing' }); expect(result).toEqual({ some: 'thing' });
}); });
}); });
});
describe('checkAuth', () => { describe('checkAuth', () => {
it('calls checkAuthService.checkAuth() without url if none is passed', async () => { it('calls checkAuthService.checkAuth() without url if none is passed', async () => {

View File

@ -22,23 +22,21 @@ describe('Events Service', () => {
}); });
it('registering to single event with one event emit works', async () => { it('registering to single event with one event emit works', async () => {
eventsService.registerForEvents().subscribe((firedEvent) => { const firedEvent = await lastValueFrom(eventsService.registerForEvents());
expect(firedEvent).toBeTruthy(); expect(firedEvent).toBeTruthy();;
expect(firedEvent).toEqual({ expect(firedEvent).toEqual({
type: EventTypes.ConfigLoaded, type: EventTypes.ConfigLoaded,
value: { myKey: 'myValue' }, value: { myKey: 'myValue' },
}); });
});
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' }); eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
}); });
it('registering to single event with multiple same event emit works', async () => { it('registering to single event with multiple same event emit works', async () => {
const spy = jasmine.createSpy('spy'); const spy = jasmine.createSpy('spy');
eventsService.registerForEvents().subscribe((firedEvent) => { const firedEvent = await lastValueFrom(eventsService.registerForEvents());
spy(firedEvent); spy(firedEvent);;
expect(firedEvent).toBeTruthy(); expect(firedEvent).toBeTruthy();
});
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' }); eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue2' }); eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue2' });
@ -54,16 +52,14 @@ describe('Events Service', () => {
}); });
it('registering to single event with multiple emit works', async () => { it('registering to single event with multiple emit works', async () => {
eventsService const firedEvent = await lastValueFrom(eventsService
.registerForEvents() .registerForEvents()
.pipe(filter((x) => x.type === EventTypes.ConfigLoaded)) .pipe(filter((x) => x.type === EventTypes.ConfigLoaded)));
.subscribe((firedEvent) => { expect(firedEvent).toBeTruthy();;
expect(firedEvent).toBeTruthy();
expect(firedEvent).toEqual({ expect(firedEvent).toEqual({
type: EventTypes.ConfigLoaded, type: EventTypes.ConfigLoaded,
value: { myKey: 'myValue' }, value: { myKey: 'myValue' },
}); });
});
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' }); eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
eventsService.fireEvent(EventTypes.NewAuthenticationResult, true); eventsService.fireEvent(EventTypes.NewAuthenticationResult, true);
}); });

9
src/testing/http.ts Normal file
View File

@ -0,0 +1,9 @@
import { HttpFeatureKind } from '@ngify/http';
import { HttpClientTestingBackend } from '@ngify/http/testing';
export function provideHttpClientTesting() {
return {
provide: HttpFeatureKind.Backend,
useClass: HttpClientTestingBackend,
};
}

View File

@ -6,3 +6,4 @@ export {
} from './spy'; } from './spy';
export { createRetriableStream } from './create-retriable-stream.helper'; export { createRetriableStream } from './create-retriable-stream.helper';
export { MockRouter, mockRouterProvider } from './router'; export { MockRouter, mockRouterProvider } from './router';
export { provideHttpClientTesting } from './http';

View File

@ -29,9 +29,6 @@ describe('UrlService Tests', () => {
mockProvider(JwtWindowCryptoService), mockProvider(JwtWindowCryptoService),
], ],
}); });
});
beforeEach(() => {
service = TestBed.inject(UrlService); service = TestBed.inject(UrlService);
loggerService = TestBed.inject(LoggerService); loggerService = TestBed.inject(LoggerService);
flowHelper = TestBed.inject(FlowHelper); flowHelper = TestBed.inject(FlowHelper);
@ -53,15 +50,15 @@ describe('UrlService Tests', () => {
{ key: 'blep', value: 'blep' }, { key: 'blep', value: 'blep' },
]; ];
params.forEach((p) => { for (const p of params) {
url.searchParams.set(p.key, p.value); url.searchParams.set(p.key, p.value);
}); }
const sut = service.getUrlWithoutQueryParameters(url); const sut = service.getUrlWithoutQueryParameters(url);
params.forEach((p) => { for (const p of params) {
expect(sut.searchParams.has(p.key)).toBeFalsy(); expect(sut.searchParams.has(p.key)).toBeFalsy();
}); }
}); });
}); });
@ -73,9 +70,9 @@ describe('UrlService Tests', () => {
{ key: 'blep', value: 'blep' }, { key: 'blep', value: 'blep' },
]; ];
params.forEach((p) => { for (const p of params) {
expected.set(p.key, p.value); expected.set(p.key, p.value);
}); }
const matchingUrls = [ const matchingUrls = [
new URL('https://any.url?doot=boop&blep=blep'), new URL('https://any.url?doot=boop&blep=blep'),
@ -87,21 +84,21 @@ describe('UrlService Tests', () => {
new URL('https://any.url?blep=blep&woop=doot'), new URL('https://any.url?blep=blep&woop=doot'),
]; ];
matchingUrls.forEach((mu) => { for (const mu of matchingUrls) {
it(`should return true for ${mu.toString()}`, () => { it(`should return true for ${mu.toString()}`, () => {
expect( expect(
service.queryParametersExist(expected, mu.searchParams) service.queryParametersExist(expected, mu.searchParams)
).toBeTruthy(); ).toBeTruthy();
}); });
}); }
nonMatchingUrls.forEach((nmu) => { for (const nmu of nonMatchingUrls) {
it(`should return false for ${nmu.toString()}`, () => { it(`should return false for ${nmu.toString()}`, () => {
expect( expect(
service.queryParametersExist(expected, nmu.searchParams) service.queryParametersExist(expected, nmu.searchParams)
).toBeFalsy(); ).toBeFalsy();
}); });
}); }
}); });
describe('isCallbackFromSts', () => { describe('isCallbackFromSts', () => {
@ -130,9 +127,9 @@ describe('UrlService Tests', () => {
}, },
]; ];
nonMatchingUrls.forEach((nmu) => { for (const nmu of nonMatchingUrls) {
expect(service.isCallbackFromSts(nmu.url, nmu.config)).toBeFalsy(); expect(service.isCallbackFromSts(nmu.url, nmu.config)).toBeFalsy();
}); }
}); });
const testingValues = [ const testingValues = [
@ -143,7 +140,7 @@ describe('UrlService Tests', () => {
{ param: 'some_param', isCallbackFromSts: false }, { param: 'some_param', isCallbackFromSts: false },
]; ];
testingValues.forEach(({ param, isCallbackFromSts }) => { for (const { param, isCallbackFromSts } of testingValues) {
it(`should return ${isCallbackFromSts} when param is ${param}`, () => { it(`should return ${isCallbackFromSts} when param is ${param}`, () => {
const result = service.isCallbackFromSts( const result = service.isCallbackFromSts(
`https://any.url/?${param}=anyvalue` `https://any.url/?${param}=anyvalue`
@ -151,7 +148,7 @@ describe('UrlService Tests', () => {
expect(result).toBe(isCallbackFromSts); expect(result).toBe(isCallbackFromSts);
}); });
}); }
}); });
describe('getUrlParameter', () => { describe('getUrlParameter', () => {
@ -1051,10 +1048,11 @@ describe('UrlService Tests', () => {
it('returns null if current flow is code flow and no redirect url is defined', async () => { it('returns null if current flow is code flow and no redirect url is defined', async () => {
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true); vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
service.getAuthorizeUrl({ configId: 'configId1' }).subscribe((result) => { const result = await lastValueFrom(
service.getAuthorizeUrl({ configId: 'configId1' })
);
expect(result).toBeNull(); expect(result).toBeNull();
}); });
});
it('returns empty string if current flow is code flow, config disabled pkce and there is a redirecturl', async () => { it('returns empty string if current flow is code flow, config disabled pkce and there is a redirecturl', async () => {
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true); vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
@ -1064,10 +1062,9 @@ describe('UrlService Tests', () => {
redirectUrl: 'some-redirectUrl', redirectUrl: 'some-redirectUrl',
} as OpenIdConfiguration; } as OpenIdConfiguration;
service.getAuthorizeUrl(config).subscribe((result) => { const result = await lastValueFrom(service.getAuthorizeUrl(config));
expect(result).toBe(''); expect(result).toBe('');
}); });
});
it('returns url if current flow is code flow, config disabled pkce, there is a redirecturl and awkep are given', async () => { it('returns url if current flow is code flow, config disabled pkce, there is a redirecturl and awkep are given', async () => {
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true); vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
@ -1093,12 +1090,11 @@ describe('UrlService Tests', () => {
() => ({ authorizationEndpoint }) () => ({ authorizationEndpoint })
); );
service.getAuthorizeUrl(config).subscribe((result) => { const result = await lastValueFrom(service.getAuthorizeUrl(config));
expect(result).toBe( expect(result).toBe(
'authorizationEndpoint?client_id=some-clientId&redirect_uri=some-redirectUrl&response_type=testResponseType&scope=testScope&nonce=undefined&state=undefined&code_challenge=some-code-challenge&code_challenge_method=S256' 'authorizationEndpoint?client_id=some-clientId&redirect_uri=some-redirectUrl&response_type=testResponseType&scope=testScope&nonce=undefined&state=undefined&code_challenge=some-code-challenge&code_challenge_method=S256'
); );
}); });
});
it('calls createUrlImplicitFlowAuthorize if current flow is NOT code flow', async () => { it('calls createUrlImplicitFlowAuthorize if current flow is NOT code flow', async () => {
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false); vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
@ -1111,11 +1107,10 @@ describe('UrlService Tests', () => {
'createUrlImplicitFlowAuthorize' 'createUrlImplicitFlowAuthorize'
); );
service.getAuthorizeUrl({ configId: 'configId1' }).subscribe(() => { await lastValueFrom(service.getAuthorizeUrl({ configId: 'configId1' }));
expect(spyCreateUrlCodeFlowAuthorize).not.toHaveBeenCalled(); expect(spyCreateUrlCodeFlowAuthorize).not.toHaveBeenCalled();
expect(spyCreateUrlImplicitFlowAuthorize).toHaveBeenCalled(); expect(spyCreateUrlImplicitFlowAuthorize).toHaveBeenCalled();
}); });
});
it('return empty string if flow is not code flow and createUrlImplicitFlowAuthorize returns falsy', async () => { it('return empty string if flow is not code flow and createUrlImplicitFlowAuthorize returns falsy', async () => {
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false); vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
@ -1124,12 +1119,11 @@ describe('UrlService Tests', () => {
.mockReturnValue(''); .mockReturnValue('');
const resultObs$ = service.getAuthorizeUrl({ configId: 'configId1' }); const resultObs$ = service.getAuthorizeUrl({ configId: 'configId1' });
resultObs$.subscribe((result) => { const result = await lastValueFrom(resultObs$);
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
expect(result).toBe(''); expect(result).toBe('');
}); });
}); });
});
describe('getRefreshSessionSilentRenewUrl', () => { describe('getRefreshSessionSilentRenewUrl', () => {
it('calls createUrlCodeFlowWithSilentRenew if current flow is code flow', () => { it('calls createUrlCodeFlowWithSilentRenew if current flow is code flow', () => {
@ -1165,12 +1159,11 @@ describe('UrlService Tests', () => {
configId: 'configId1', configId: 'configId1',
}); });
resultObs$.subscribe((result) => { const result = await lastValueFrom(resultObs$);
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
expect(result).toBe(''); expect(result).toBe('');
}); });
}); });
});
describe('createBodyForCodeFlowCodeRequest', () => { describe('createBodyForCodeFlowCodeRequest', () => {
it('returns null if no code verifier is set', () => { it('returns null if no code verifier is set', () => {
@ -1351,10 +1344,9 @@ describe('UrlService Tests', () => {
redirectUrl: '', redirectUrl: '',
}); });
resultObs$.subscribe((result) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe(null); expect(result).toBe(null);
}); });
});
it('returns basic URL with no extras if properties are given', async () => { it('returns basic URL with no extras if properties are given', async () => {
const config = { const config = {
@ -1380,12 +1372,11 @@ describe('UrlService Tests', () => {
const resultObs$ = service.createBodyForParCodeFlowRequest(config); const resultObs$ = service.createBodyForParCodeFlowRequest(config);
resultObs$.subscribe((result) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe( expect(result).toBe(
'client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256' 'client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256'
); );
}); });
});
it('returns basic URL with hdParam if properties are given', async () => { it('returns basic URL with hdParam if properties are given', async () => {
const config = { const config = {
@ -1411,12 +1402,11 @@ describe('UrlService Tests', () => {
const resultObs$ = service.createBodyForParCodeFlowRequest(config); const resultObs$ = service.createBodyForParCodeFlowRequest(config);
resultObs$.subscribe((result) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe( expect(result).toBe(
'client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256&hd=testHdParam' 'client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256&hd=testHdParam'
); );
}); });
});
it('returns basic URL with hdParam and custom params if properties are given', async () => { it('returns basic URL with hdParam and custom params if properties are given', async () => {
const config = { const config = {
@ -1442,12 +1432,11 @@ describe('UrlService Tests', () => {
const resultObs$ = service.createBodyForParCodeFlowRequest(config); const resultObs$ = service.createBodyForParCodeFlowRequest(config);
resultObs$.subscribe((result) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe( expect(result).toBe(
'client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256&hd=testHdParam&any=thing' 'client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256&hd=testHdParam&any=thing'
); );
}); });
});
it('returns basic URL with hdParam and custom params and passed cutom params if properties are given', async () => { it('returns basic URL with hdParam and custom params and passed cutom params if properties are given', async () => {
const config = { const config = {
@ -1477,18 +1466,18 @@ describe('UrlService Tests', () => {
}, },
}); });
resultObs$.subscribe((result) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe( expect(result).toBe(
'client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256&hd=testHdParam&any=thing&any=otherThing' 'client_id=testClientId&redirect_uri=testRedirectUrl&response_type=testResponseType&scope=testScope&nonce=testNonce&state=testState&code_challenge=testCodeChallenge&code_challenge_method=S256&hd=testHdParam&any=thing&any=otherThing'
); );
}); });
}); });
});
describe('createUrlImplicitFlowWithSilentRenew', () => { describe('createUrlImplicitFlowWithSilentRenew', () => {
it('returns null if silentrenewUrl is falsy', () => { it('returns null if silentrenewUrl is falsy', () => {
const state = 'testState'; const state = 'testState';
const nonce = 'testNonce'; const nonce = 'testNonce';
// biome-ignore lint/suspicious/noEvolvingTypes: <explanation>
const silentRenewUrl = null; const silentRenewUrl = null;
vi.spyOn( vi.spyOn(
@ -1582,6 +1571,7 @@ describe('UrlService Tests', () => {
it('returns empty string if silentrenewUrl is falsy', async () => { it('returns empty string if silentrenewUrl is falsy', async () => {
const state = 'testState'; const state = 'testState';
const nonce = 'testNonce'; const nonce = 'testNonce';
// biome-ignore lint/suspicious/noEvolvingTypes: <explanation>
const silentRenewUrl = null; const silentRenewUrl = null;
const codeVerifier = 'codeVerifier'; const codeVerifier = 'codeVerifier';
const codeChallenge = 'codeChallenge '; const codeChallenge = 'codeChallenge ';
@ -1606,10 +1596,9 @@ describe('UrlService Tests', () => {
const resultObs$ = serviceAsAny.createUrlCodeFlowWithSilentRenew(config); const resultObs$ = serviceAsAny.createUrlCodeFlowWithSilentRenew(config);
resultObs$.subscribe((result: any) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe(''); expect(result).toBe('');
}); });
});
it('returns correct URL if wellknownendpoints are given', async () => { it('returns correct URL if wellknownendpoints are given', async () => {
const state = 'testState'; const state = 'testState';
@ -1650,12 +1639,11 @@ describe('UrlService Tests', () => {
const resultObs$ = serviceAsAny.createUrlCodeFlowWithSilentRenew(config); const resultObs$ = serviceAsAny.createUrlCodeFlowWithSilentRenew(config);
resultObs$.subscribe((result: any) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe( expect(result).toBe(
`authorizationEndpoint?client_id=${clientId}&redirect_uri=http%3A%2F%2Fany-url.com&response_type=${responseType}&scope=${scope}&nonce=${nonce}&state=${state}&prompt=none` `authorizationEndpoint?client_id=${clientId}&redirect_uri=http%3A%2F%2Fany-url.com&response_type=${responseType}&scope=${scope}&nonce=${nonce}&state=${state}&prompt=none`
); );
}); });
});
it('returns empty string if no wellknownendpoints are given', async () => { it('returns empty string if no wellknownendpoints are given', async () => {
const state = 'testState'; const state = 'testState';
@ -1692,11 +1680,10 @@ describe('UrlService Tests', () => {
const resultObs$ = serviceAsAny.createUrlCodeFlowWithSilentRenew(config); const resultObs$ = serviceAsAny.createUrlCodeFlowWithSilentRenew(config);
resultObs$.subscribe((result: any) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe(''); expect(result).toBe('');
}); });
}); });
});
describe('createUrlImplicitFlowAuthorize', () => { describe('createUrlImplicitFlowAuthorize', () => {
it('returns correct URL if wellknownendpoints are given', () => { it('returns correct URL if wellknownendpoints are given', () => {
@ -1793,6 +1780,7 @@ describe('UrlService Tests', () => {
it('returns null if redirectUrl is falsy', async () => { it('returns null if redirectUrl is falsy', async () => {
const state = 'testState'; const state = 'testState';
const nonce = 'testNonce'; const nonce = 'testNonce';
// biome-ignore lint/suspicious/noEvolvingTypes: <explanation>
const redirectUrl = null; const redirectUrl = null;
const config = { const config = {
redirectUrl, redirectUrl,
@ -1808,10 +1796,9 @@ describe('UrlService Tests', () => {
const resultObs$ = serviceAsAny.createUrlCodeFlowAuthorize(config); const resultObs$ = serviceAsAny.createUrlCodeFlowAuthorize(config);
resultObs$.subscribe((result: any) => { const result = await lastValueFrom(resultObs$);
expect(result).toBeNull(); expect(result).toBeNull();
}); });
});
it('returns correct URL if wellknownendpoints are given', async () => { it('returns correct URL if wellknownendpoints are given', async () => {
const state = 'testState'; const state = 'testState';
@ -1851,12 +1838,11 @@ describe('UrlService Tests', () => {
const resultObs$ = serviceAsAny.createUrlCodeFlowAuthorize(config); const resultObs$ = serviceAsAny.createUrlCodeFlowAuthorize(config);
resultObs$.subscribe((result: any) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe( expect(result).toBe(
`authorizationEndpoint?client_id=clientId&redirect_uri=http%3A%2F%2Fany-url.com&response_type=${responseType}&scope=${scope}&nonce=${nonce}&state=${state}` `authorizationEndpoint?client_id=clientId&redirect_uri=http%3A%2F%2Fany-url.com&response_type=${responseType}&scope=${scope}&nonce=${nonce}&state=${state}`
); );
}); });
});
it('returns correct URL if wellknownendpoints and custom params are given', async () => { it('returns correct URL if wellknownendpoints and custom params are given', async () => {
const state = 'testState'; const state = 'testState';
@ -1901,12 +1887,11 @@ describe('UrlService Tests', () => {
customParams: { to: 'add', as: 'well' }, customParams: { to: 'add', as: 'well' },
}); });
resultObs$.subscribe((result: any) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe( expect(result).toBe(
`authorizationEndpoint?client_id=clientId&redirect_uri=http%3A%2F%2Fany-url.com&response_type=${responseType}&scope=${scope}&nonce=${nonce}&state=${state}&to=add&as=well` `authorizationEndpoint?client_id=clientId&redirect_uri=http%3A%2F%2Fany-url.com&response_type=${responseType}&scope=${scope}&nonce=${nonce}&state=${state}&to=add&as=well`
); );
}); });
});
it('returns empty string if no wellknownendpoints are given', async () => { it('returns empty string if no wellknownendpoints are given', async () => {
const state = 'testState'; const state = 'testState';
@ -1939,11 +1924,10 @@ describe('UrlService Tests', () => {
const resultObs$ = serviceAsAny.createUrlCodeFlowAuthorize(config); const resultObs$ = serviceAsAny.createUrlCodeFlowAuthorize(config);
resultObs$.subscribe((result: any) => { const result = await lastValueFrom(resultObs$);
expect(result).toBe(''); expect(result).toBe('');
}); });
}); });
});
describe('getEndSessionUrl', () => { describe('getEndSessionUrl', () => {
it('returns null if no config given', () => { it('returns null if no config given', () => {

View File

@ -1,6 +1,5 @@
import { TestBed } from '@/testing'; import { TestBed } from '@/testing';
import { base64url } from 'rfc4648'; import { base64url } from 'rfc4648';
import { vi } from 'vitest';
import { CryptoService } from '../utils/crypto/crypto.service'; import { CryptoService } from '../utils/crypto/crypto.service';
import { JwkWindowCryptoService } from './jwk-window-crypto.service'; import { JwkWindowCryptoService } from './jwk-window-crypto.service';
@ -42,9 +41,6 @@ describe('JwkWindowCryptoService', () => {
imports: [], imports: [],
providers: [JwkWindowCryptoService, CryptoService], providers: [JwkWindowCryptoService, CryptoService],
}); });
});
beforeEach(async () => {
service = TestBed.inject(JwkWindowCryptoService); service = TestBed.inject(JwkWindowCryptoService);
}); });
@ -53,22 +49,21 @@ describe('JwkWindowCryptoService', () => {
}); });
describe('importVerificationKey', () => { describe('importVerificationKey', () => {
it('returns instance of CryptoKey when valid input is provided', (done) => { it('returns instance of CryptoKey when valid input is provided', async () => {
const promises = keys.map((key) => const promises = keys.map((key) =>
service.importVerificationKey(key, alg) service.importVerificationKey(key, alg)
); );
Promise.all(promises).then((values) => { Promise.all(promises).then((values) => {
values.forEach((value) => { for (const value of values) {
expect(value).toBeInstanceOf(CryptoKey); expect(value).toBeInstanceOf(CryptoKey);
}); }
done();
}); });
}); });
}); });
describe('verifyKey', () => { describe('verifyKey', () => {
it('returns true when valid input is provided', (done) => { it('returns true when valid input is provided', async () => {
const headerAndPayloadString = const headerAndPayloadString =
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0'; 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0';
const signatureString = const signatureString =
@ -77,17 +72,13 @@ describe('JwkWindowCryptoService', () => {
loose: true, loose: true,
}); });
service const value = await service
.importVerificationKey(key3, alg) .importVerificationKey(key3, alg)
.then((c) => .then((c) =>
service.verifyKey(alg, c, signature, headerAndPayloadString) service.verifyKey(alg, c, signature, headerAndPayloadString)
) );
.then((value) => {
expect(value).toEqual(true); expect(value).toEqual(true);
})
.finally(() => {
done();
});
}); });
}); });
}); });

View File

@ -28,9 +28,8 @@ describe('JwtWindowCryptoService', () => {
'44445543344242132145455aaabbdc3b4' '44445543344242132145455aaabbdc3b4'
); );
observable.subscribe((value) => { const value = await lastValueFrom(observable);
expect(value).toBe(outcome); expect(value).toBe(outcome);
}); });
}); });
}); });
});

View File

@ -693,10 +693,9 @@ describe('State Validation Service', () => {
config config
); );
isValidObs$.subscribe((isValid) => { const isValid = await lastValueFrom(isValidObs$);
expect(isValid.authResponseIsValid).toBe(false); expect(isValid.authResponseIsValid).toBe(false);
}); });
});
it('should return invalid context error', async () => { it('should return invalid context error', async () => {
vi.spyOn( vi.spyOn(
@ -730,10 +729,9 @@ describe('State Validation Service', () => {
config config
); );
isValidObs$.subscribe((isValid) => { const isValid = await lastValueFrom(isValidObs$);
expect(isValid.authResponseIsValid).toBe(false); expect(isValid.authResponseIsValid).toBe(false);
}); });
});
it('should return invalid result if validateIdTokenExpNotExpired is false', async () => { it('should return invalid result if validateIdTokenExpNotExpired is false', async () => {
vi.spyOn( vi.spyOn(
@ -826,17 +824,16 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback id token expired' 'authCallback id token expired'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);
}); });
});
it('should return invalid result if validateStateFromHashCallback is false', async () => { it('should return invalid result if validateStateFromHashCallback is false', async () => {
const readSpy = vi.spyOn(storagePersistenceService, 'read'); const readSpy = vi.spyOn(storagePersistenceService, 'read');
@ -879,17 +876,16 @@ describe('State Validation Service', () => {
tokenValidationService.validateStateFromHashCallback tokenValidationService.validateStateFromHashCallback
).toHaveBeenCalled(); ).toHaveBeenCalled();
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback incorrect state' 'authCallback incorrect state'
); );;
expect(state.accessToken).toBe(''); expect(state.accessToken).toBe('');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);;
expect(state.decodedIdToken).toBeDefined(); expect(state.decodedIdToken).toBeDefined();;
expect(state.idToken).toBe(''); expect(state.idToken).toBe('');
}); });
});
it('access_token should equal result.access_token and is valid if response_type is "id_token token"', async () => { it('access_token should equal result.access_token and is valid if response_type is "id_token token"', async () => {
vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue( vi.spyOn(tokenHelperService, 'getPayloadFromToken').mockReturnValue(
@ -977,13 +973,12 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(true); expect(state.authResponseIsValid).toBe(true);
}); });
});
it('should return invalid result if validateSignatureIdToken is false', async () => { it('should return invalid result if validateSignatureIdToken is false', async () => {
vi.spyOn( vi.spyOn(
@ -1031,18 +1026,16 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logDebugSpy).toBeCalledWith([ expect(logDebugSpy).toBeCalledWith([
[config, 'authCallback Signature validation failed id_token'], [config, 'authCallback Signature validation failed id_token'],
[config, 'authCallback token(s) invalid'], [config, 'authCallback token(s) invalid'],
]); ]);;
expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.decodedIdToken).toBe('decoded_id_token');
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);
}); });
});
it('should return invalid result if validateIdTokenNonce is false', async () => { it('should return invalid result if validateIdTokenNonce is false', async () => {
vi.spyOn( vi.spyOn(
@ -1093,17 +1086,16 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback incorrect nonce, did you call the checkAuth() method multiple times?' 'authCallback incorrect nonce, did you call the checkAuth() method multiple times?'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);
}); });
});
it('should return invalid result if validateRequiredIdToken is false', async () => { it('should return invalid result if validateRequiredIdToken is false', async () => {
vi.spyOn( vi.spyOn(
@ -1162,21 +1154,20 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logDebugSpy).toHaveBeenCalledWith( expect(logDebugSpy).toHaveBeenCalledWith(
config, config,
'authCallback Validation, one of the REQUIRED properties missing from id_token' 'authCallback Validation, one of the REQUIRED properties missing from id_token'
); );;
expect(logDebugSpy).toHaveBeenCalledWith( expect(logDebugSpy).toHaveBeenCalledWith(
config, config,
'authCallback token(s) invalid' 'authCallback token(s) invalid'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);
}); });
});
it('should return invalid result if validateIdTokenIatMaxOffset is false', async () => { it('should return invalid result if validateIdTokenIatMaxOffset is false', async () => {
vi.spyOn( vi.spyOn(
@ -1238,17 +1229,16 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback Validation, iat rejected id_token was issued too far away from the current time' 'authCallback Validation, iat rejected id_token was issued too far away from the current time'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);
}); });
});
it('should return invalid result if validateIdTokenIss is false and has authWellKnownEndPoints', async () => { it('should return invalid result if validateIdTokenIss is false and has authWellKnownEndPoints', async () => {
vi.spyOn( vi.spyOn(
@ -1317,17 +1307,16 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback incorrect iss does not match authWellKnownEndpoints issuer' 'authCallback incorrect iss does not match authWellKnownEndpoints issuer'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);
}); });
});
it('should return invalid result if validateIdTokenIss is false and has no authWellKnownEndPoints', async () => { it('should return invalid result if validateIdTokenIss is false and has no authWellKnownEndPoints', async () => {
vi.spyOn( vi.spyOn(
@ -1384,19 +1373,17 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authWellKnownEndpoints is undefined' 'authWellKnownEndpoints is undefined'
); );;
expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.authResponseIsValid).toBe(false);;
expect(state.authResponseIsValid).toBe(false);
expect(state.state).toBe(ValidationResult.NoAuthWellKnownEndPoints); expect(state.state).toBe(ValidationResult.NoAuthWellKnownEndPoints);
}); });
});
it('should return invalid result if validateIdTokenAud is false', async () => { it('should return invalid result if validateIdTokenAud is false', async () => {
vi.spyOn( vi.spyOn(
@ -1463,17 +1450,16 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback incorrect aud' 'authCallback incorrect aud'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);
}); });
});
it('should return invalid result if validateIdTokenAzpExistsIfMoreThanOneAud is false', async () => { it('should return invalid result if validateIdTokenAzpExistsIfMoreThanOneAud is false', async () => {
vi.spyOn( vi.spyOn(
@ -1544,18 +1530,17 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback missing azp' 'authCallback missing azp'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);;
expect(state.state).toBe(ValidationResult.IncorrectAzp); expect(state.state).toBe(ValidationResult.IncorrectAzp);
}); });
});
it('should return invalid result if validateIdTokenAzpValid is false', async () => { it('should return invalid result if validateIdTokenAzpValid is false', async () => {
vi.spyOn( vi.spyOn(
@ -1630,18 +1615,17 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback incorrect azp' 'authCallback incorrect azp'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);;
expect(state.state).toBe(ValidationResult.IncorrectAzp); expect(state.state).toBe(ValidationResult.IncorrectAzp);
}); });
});
it('should return invalid result if isIdTokenAfterRefreshTokenRequestValid is false', async () => { it('should return invalid result if isIdTokenAfterRefreshTokenRequestValid is false', async () => {
vi.spyOn( vi.spyOn(
@ -1720,20 +1704,19 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback pre, post id_token claims do not match in refresh' 'authCallback pre, post id_token claims do not match in refresh'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);;
expect(state.state).toBe( expect(state.state).toBe(
ValidationResult.IncorrectIdTokenClaimsAfterRefresh ValidationResult.IncorrectIdTokenClaimsAfterRefresh
); );
}); });
});
it('Reponse is valid if authConfiguration.response_type does not equal "id_token token"', async () => { it('Reponse is valid if authConfiguration.response_type does not equal "id_token token"', async () => {
vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockReturnValue( vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockReturnValue(
@ -1824,21 +1807,20 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logDebugSpy).toHaveBeenCalledWith( expect(logDebugSpy).toHaveBeenCalledWith(
config, config,
'authCallback token(s) validated, continue' 'authCallback token(s) validated, continue'
); );;
expect(logDebugSpy).toHaveBeenCalledWith( expect(logDebugSpy).toHaveBeenCalledWith(
config, config,
'authCallback token(s) invalid' 'authCallback token(s) invalid'
); );;
expect(state.accessToken).toBe(''); expect(state.accessToken).toBe('');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(true); expect(state.authResponseIsValid).toBe(true);
}); });
});
it('Response is invalid if validateIdTokenAtHash is false', async () => { it('Response is invalid if validateIdTokenAtHash is false', async () => {
vi.spyOn( vi.spyOn(
@ -1930,17 +1912,16 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith( expect(logWarningSpy).toHaveBeenCalledExactlyOnceWith(
config, config,
'authCallback incorrect at_hash' 'authCallback incorrect at_hash'
); );;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');;
expect(state.decodedIdToken).toBe('decoded_id_token'); expect(state.decodedIdToken).toBe('decoded_id_token');;
expect(state.authResponseIsValid).toBe(false); expect(state.authResponseIsValid).toBe(false);
}); });
});
it('should return valid result if validateIdTokenIss is false and iss_validation_off is true', async () => { it('should return valid result if validateIdTokenIss is false and iss_validation_off is true', async () => {
config.issValidationOff = true; config.issValidationOff = true;
@ -2028,18 +2009,17 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(logDebugSpy).toBeCalledWith([ expect(logDebugSpy).toBeCalledWith([
[config, 'iss validation is turned off, this is not recommended!'], [config, 'iss validation is turned off, this is not recommended!'],
[config, 'authCallback token(s) validated, continue'], [config, 'authCallback token(s) validated, continue'],
]); ]);;
expect(state.state).toBe(ValidationResult.Ok); expect(state.state).toBe(ValidationResult.Ok);;
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.authResponseIsValid).toBe(true); expect(state.authResponseIsValid).toBe(true);;
expect(state.decodedIdToken).toBeDefined(); expect(state.decodedIdToken).toBeDefined();;
expect(state.idToken).toBe('id_tokenTEST'); expect(state.idToken).toBe('id_tokenTEST');
}); });
});
it('should return valid if there is no id_token', async () => { it('should return valid if there is no id_token', async () => {
vi.spyOn( vi.spyOn(
@ -2114,13 +2094,12 @@ describe('State Validation Service', () => {
config config
); );
stateObs$.subscribe((state) => { const state = await lastValueFrom(stateObs$);
expect(state.accessToken).toBe('access_tokenTEST'); expect(state.accessToken).toBe('access_tokenTEST');;
expect(state.idToken).toBe(''); expect(state.idToken).toBe('');;
expect(state.decodedIdToken).toBeDefined(); expect(state.decodedIdToken).toBeDefined();;
expect(state.authResponseIsValid).toBe(true); expect(state.authResponseIsValid).toBe(true);
}); });
});
it('should return OK if disableIdTokenValidation is true', async () => { it('should return OK if disableIdTokenValidation is true', async () => {
vi.spyOn( vi.spyOn(
@ -2154,11 +2133,10 @@ describe('State Validation Service', () => {
config config
); );
isValidObs$.subscribe((isValid) => { const isValid = await lastValueFrom(isValidObs$);
expect(isValid.state).toBe(ValidationResult.Ok); expect(isValid.state).toBe(ValidationResult.Ok);;
expect(isValid.authResponseIsValid).toBe(true); expect(isValid.authResponseIsValid).toBe(true);
}); });
});
it('should return OK if disableIdTokenValidation is true', async () => { it('should return OK if disableIdTokenValidation is true', async () => {
vi.spyOn( vi.spyOn(
@ -2192,11 +2170,10 @@ describe('State Validation Service', () => {
config config
); );
isValidObs$.subscribe((isValid) => { const isValid = await lastValueFrom(isValidObs$);
expect(isValid.state).toBe(ValidationResult.Ok); expect(isValid.state).toBe(ValidationResult.Ok);;
expect(isValid.authResponseIsValid).toBe(true); expect(isValid.authResponseIsValid).toBe(true);
}); });
});
it('should return OK if disableIdTokenValidation is false but inrefreshtokenflow and no id token is returned', async () => { it('should return OK if disableIdTokenValidation is false but inrefreshtokenflow and no id token is returned', async () => {
vi.spyOn( vi.spyOn(
@ -2230,10 +2207,9 @@ describe('State Validation Service', () => {
config config
); );
isValidObs$.subscribe((isValid) => { const isValid = await lastValueFrom(isValidObs$);
expect(isValid.state).toBe(ValidationResult.Ok); expect(isValid.state).toBe(ValidationResult.Ok);;
expect(isValid.authResponseIsValid).toBe(true); expect(isValid.authResponseIsValid).toBe(true);
}); });
}); });
}); });
});

View File

@ -28,9 +28,6 @@ describe('TokenValidationService', () => {
CryptoService, CryptoService,
], ],
}); });
});
beforeEach(() => {
tokenValidationService = TestBed.inject(TokenValidationService); tokenValidationService = TestBed.inject(TokenValidationService);
tokenHelperService = TestBed.inject(TokenHelperService); tokenHelperService = TestBed.inject(TokenHelperService);
jwtWindowCryptoService = TestBed.inject(JwtWindowCryptoService); jwtWindowCryptoService = TestBed.inject(JwtWindowCryptoService);
@ -506,10 +503,9 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
valueFalse$.subscribe((valueFalse) => { const valueFalse = await lastValueFrom(valueFalse$);
expect(valueFalse).toEqual(false); expect(valueFalse).toEqual(false);
}); });
});
it('returns true if no idToken is passed', async () => { it('returns true if no idToken is passed', async () => {
const valueFalse$ = tokenValidationService.validateSignatureIdToken( const valueFalse$ = tokenValidationService.validateSignatureIdToken(
@ -518,10 +514,9 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
valueFalse$.subscribe((valueFalse) => { const valueFalse = await lastValueFrom(valueFalse$);
expect(valueFalse).toEqual(true); expect(valueFalse).toEqual(true);
}); });
});
it('returns false if jwtkeys has no keys-property', async () => { it('returns false if jwtkeys has no keys-property', async () => {
const valueFalse$ = tokenValidationService.validateSignatureIdToken( const valueFalse$ = tokenValidationService.validateSignatureIdToken(
@ -530,10 +525,9 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
valueFalse$.subscribe((valueFalse) => { const valueFalse = await lastValueFrom(valueFalse$);
expect(valueFalse).toEqual(false); expect(valueFalse).toEqual(false);
}); });
});
it('returns false if header data has no header data', async () => { it('returns false if header data has no header data', async () => {
vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({}); vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({});
@ -548,10 +542,9 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
valueFalse$.subscribe((valueFalse) => { const valueFalse = await lastValueFrom(valueFalse$);
expect(valueFalse).toEqual(false); expect(valueFalse).toEqual(false);
}); });
});
it('returns false if header data alg property does not exist in keyalgorithms', async () => { it('returns false if header data alg property does not exist in keyalgorithms', async () => {
vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({ vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({
@ -568,12 +561,11 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
valueFalse$.subscribe((valueFalse) => { const valueFalse = await lastValueFrom(valueFalse$);
expect(valueFalse).toEqual(false); expect(valueFalse).toEqual(false);
}); });
});
it('returns false if header data has kid property and jwtKeys has same kid property but they are not valid with the token', (done) => { it('returns false if header data has kid property and jwtKeys has same kid property but they are not valid with the token', async () => {
const kid = '5626CE6A8F4F5FCD79C6642345282CA76D337548'; const kid = '5626CE6A8F4F5FCD79C6642345282CA76D337548';
vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({ vi.spyOn(tokenHelperService, 'getHeaderFromToken').mockReturnValue({
@ -605,13 +597,11 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
valueFalse$.subscribe((valueFalse) => { const valueFalse = await lastValueFrom(valueFalse$);
expect(valueFalse).toEqual(false); expect(valueFalse).toEqual(false);
done();
});
}); });
it('should return true if valid input is provided', (done) => { it('should return true if valid input is provided', async () => {
const idToken = const idToken =
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoiMTIzNDU2IiwiYXVkIjoibXlfY2xpZW50X2lkIiwiZXhwIjoxMzExMjgxOTcwLCJpYXQiOjEzMTEyODA5NzAsIm5hbWUiOiJKYW5lIERvZSIsImdpdmVuX25hbWUiOiJKYW5lIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJiaXJ0aGRhdGUiOiIxOTkwLTEwLTMxIiwiZW1haWwiOiJqYW5lZG9lQGV4YW1wbGUuY29tIiwicGljdHVyZSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vamFuZWRvZS9tZS5qcGcifQ.SY0ilps7yKYmYCc41zNOatfmAFhOtDYwuIT80qrHMl_4FEO2WFWSv-aDl4QfTSKY9A6MMP6xy0Z_8Kk7NeRwIV7FVScMLnPvVzs9pxza0e_rl6hmZLb5P5n4AEINwn46X9XmRB5W3EZO_x2LG65_g3NZFiPrzOC1Fs_6taJl7TfI8lOveYDoJyXCWYQMS3Oh5MM9S8W-Hc29_qJLH-kixm1S01qoICRPDGMRwhtAu1DHjwWQp9Ycfz6g3uyb7N1imBvI49t1CwWy02_mQ3g-7e7bOP1Ax2kgrwnJgsVBDULnyCZG9PE8T0CHZl_fErZtvbJJ0jdoZ1fyr48906am2w'; 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoiMTIzNDU2IiwiYXVkIjoibXlfY2xpZW50X2lkIiwiZXhwIjoxMzExMjgxOTcwLCJpYXQiOjEzMTEyODA5NzAsIm5hbWUiOiJKYW5lIERvZSIsImdpdmVuX25hbWUiOiJKYW5lIiwiZmFtaWx5X25hbWUiOiJEb2UiLCJiaXJ0aGRhdGUiOiIxOTkwLTEwLTMxIiwiZW1haWwiOiJqYW5lZG9lQGV4YW1wbGUuY29tIiwicGljdHVyZSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vamFuZWRvZS9tZS5qcGcifQ.SY0ilps7yKYmYCc41zNOatfmAFhOtDYwuIT80qrHMl_4FEO2WFWSv-aDl4QfTSKY9A6MMP6xy0Z_8Kk7NeRwIV7FVScMLnPvVzs9pxza0e_rl6hmZLb5P5n4AEINwn46X9XmRB5W3EZO_x2LG65_g3NZFiPrzOC1Fs_6taJl7TfI8lOveYDoJyXCWYQMS3Oh5MM9S8W-Hc29_qJLH-kixm1S01qoICRPDGMRwhtAu1DHjwWQp9Ycfz6g3uyb7N1imBvI49t1CwWy02_mQ3g-7e7bOP1Ax2kgrwnJgsVBDULnyCZG9PE8T0CHZl_fErZtvbJJ0jdoZ1fyr48906am2w';
const idTokenParts = idToken.split('.'); const idTokenParts = idToken.split('.');
@ -644,15 +634,13 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
valueTrue$.subscribe((valueTrue) => { const valueTrue = await lastValueFrom(valueTrue$);
expect(valueTrue).toEqual(true); expect(valueTrue).toEqual(true);
done();
});
}); });
}); });
describe('validateIdTokenAtHash', () => { describe('validateIdTokenAtHash', () => {
it('returns true if sha is sha256 and generated hash equals atHash param', (done) => { it('returns true if sha is sha256 and generated hash equals atHash param', async () => {
const accessToken = 'iGU3DhbPoDljiYtr0oepxi7zpT8BsjdU7aaXcdq-DPk'; const accessToken = 'iGU3DhbPoDljiYtr0oepxi7zpT8BsjdU7aaXcdq-DPk';
const atHash = '-ODC_7Go_UIUTC8nP4k2cA'; const atHash = '-ODC_7Go_UIUTC8nP4k2cA';
@ -663,10 +651,8 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
result$.subscribe((result) => { const result = await lastValueFrom(result$);
expect(result).toEqual(true); expect(result).toEqual(true);
done();
});
}); });
it('returns false if sha is sha256 and generated hash does not equal atHash param', async () => { it('returns false if sha is sha256 and generated hash does not equal atHash param', async () => {
@ -686,15 +672,14 @@ describe('TokenValidationService', () => {
expect(result).toEqual(false); expect(result).toEqual(false);
}); });
it('returns true if sha is sha256 and generated hash does equal atHash param', (done) => { it('returns true if sha is sha256 and generated hash does equal atHash param', async () => {
const accessToken = const accessToken =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg'; 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
const atHash = 'good'; const atHash = 'good';
vi.spyOn(jwtWindowCryptoService, 'generateAtHash').mockReturnValues( vi.spyOn(jwtWindowCryptoService, 'generateAtHash')
of('notEqualsGood'), .mockReturnValueOnce(of('notEqualsGood'))
of('good') .mockReturnValueOnce(of('good'));
);
const result$ = tokenValidationService.validateIdTokenAtHash( const result$ = tokenValidationService.validateIdTokenAtHash(
accessToken, accessToken,
@ -703,13 +688,11 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
result$.subscribe((result) => { const result = await lastValueFrom(result$);
expect(result).toEqual(true); expect(result).toEqual(true);
done();
});
}); });
it('returns false if sha is sha384 and generated hash does not equal atHash param', (done) => { it('returns false if sha is sha384 and generated hash does not equal atHash param', async () => {
const accessToken = const accessToken =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg'; 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
const atHash = 'bad'; const atHash = 'bad';
@ -721,13 +704,11 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
result$.subscribe((result) => { const result = await lastValueFrom(result$);
expect(result).toEqual(false); expect(result).toEqual(false);
done();
});
}); });
it('returns false if sha is sha512 and generated hash does not equal atHash param', (done) => { it('returns false if sha is sha512 and generated hash does not equal atHash param', async () => {
const accessToken = const accessToken =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg'; 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1jNTdkTzZRR1RWQndhTmsifQ.eyJleHAiOjE1ODkyMTAwODYsIm5iZiI6MTU4OTIwNjQ4NiwidmVyIjoiMS4wIiwiaXNzIjoiaHR0cHM6Ly9kYW1pZW5ib2QuYjJjbG9naW4uY29tL2EwOTU4ZjQ1LTE5NWItNDAzNi05MjU5LWRlMmY3ZTU5NGRiNi92Mi4wLyIsInN1YiI6ImY4MzZmMzgwLTNjNjQtNDgwMi04ZGJjLTAxMTk4MWMwNjhmNSIsImF1ZCI6ImYxOTM0YTZlLTk1OGQtNDE5OC05ZjM2LTYxMjdjZmM0Y2RiMyIsIm5vbmNlIjoiMDA3YzQxNTNiNmEwNTE3YzBlNDk3NDc2ZmIyNDk5NDhlYzVjbE92UVEiLCJpYXQiOjE1ODkyMDY0ODYsImF1dGhfdGltZSI6MTU4OTIwNjQ4NiwibmFtZSI6ImRhbWllbmJvZCIsImVtYWlscyI6WyJkYW1pZW5AZGFtaWVuYm9kLm9ubWljcm9zb2Z0LmNvbSJdLCJ0ZnAiOiJCMkNfMV9iMmNwb2xpY3lkYW1pZW4iLCJhdF9oYXNoIjoiWmswZktKU19wWWhPcE04SUJhMTJmdyJ9.E5Z-0kOzNU7LBkeVHHMyNoER8TUapGzUUfXmW6gVu4v6QMM5fQ4sJ7KC8PHh8lBFYiCnaDiTtpn3QytUwjXEFnLDAX5qcZT1aPoEgL_OmZMC-8y-4GyHp35l7VFD4iNYM9fJmLE8SYHTVl7eWPlXSyz37Ip0ciiV0Fd6eoksD_aVc-hkIqngDfE4fR8ZKfv4yLTNN_SfknFfuJbZ56yN-zIBL4GkuHsbQCBYpjtWQ62v98p1jO7NhHKV5JP2ec_Ge6oYc_bKTrE6OIX38RJ2rIm7zU16mtdjnl_350Nw3ytHcTPnA1VpP_VLElCfe83jr5aDHc_UQRYaAcWlOgvmVg';
const atHash = 'bad'; const atHash = 'bad';
@ -739,10 +720,8 @@ describe('TokenValidationService', () => {
{ configId: 'configId1' } { configId: 'configId1' }
); );
result$.subscribe((result) => { const result = await lastValueFrom(result$);
expect(result).toEqual(false); expect(result).toEqual(false);
done();
});
}); });
}); });
@ -817,8 +796,8 @@ describe('TokenValidationService', () => {
}, },
]; ];
testCases.forEach(({ date, offsetSeconds, expectedResult }) => { for (const { date, offsetSeconds, expectedResult } of testCases) {
it(`returns ${expectedResult} if ${date} is given with an offset of ${offsetSeconds}`, () => { it(`returns $expectedResultif ${date} is given with an offset of $offsetSeconds`, () => {
const notExpired = tokenValidationService.validateAccessTokenNotExpired( const notExpired = tokenValidationService.validateAccessTokenNotExpired(
date as Date, date as Date,
{ configId: 'configId1' }, { configId: 'configId1' },
@ -827,7 +806,7 @@ describe('TokenValidationService', () => {
expect(notExpired).toEqual(expectedResult); expect(notExpired).toEqual(expectedResult);
}); });
}); }
}); });
describe('hasIdTokenExpired', () => { describe('hasIdTokenExpired', () => {