feat: init
This commit is contained in:
parent
da0d9855da
commit
1785df25e2
@ -1,5 +1,7 @@
|
||||
# Angular Lib for OpenID Connect & OAuth2
|
||||
|
||||
TODO
|
||||
|
||||
 [](https://www.npmjs.com/package/oidc-client-rx) [](https://www.npmjs.com/package/oidc-client-rx) [](https://www.npmjs.com/package/oidc-client-rx) [](https://github.com/prettier/prettier) [](https://coveralls.io/github/damienbod/oidc-client-rx?branch=main)
|
||||
|
||||
<p align="center">
|
||||
@ -155,7 +157,7 @@ const token = this.oidcSecurityService.getAccessToken().subscribe(...);
|
||||
And then you can use it in the HttpHeaders
|
||||
|
||||
```ts
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
|
||||
const token = this.oidcSecurityServices.getAccessToken().subscribe((token) => {
|
||||
const httpOptions = {
|
||||
|
@ -18,8 +18,14 @@
|
||||
}
|
||||
},
|
||||
"files": {
|
||||
"ignore": [
|
||||
".vscode/*.json"
|
||||
]
|
||||
}
|
||||
"ignore": [".vscode/*.json"]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"include": ["src/**/*.spec.ts", "src/test.ts", "test"],
|
||||
"javascript": {
|
||||
"globals": ["describe", "beforeEach", "it", "expect"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('@angular-devkit/build-angular/plugins/karma'),
|
||||
],
|
||||
client: {
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
},
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true, // removes the duplicated traces
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: require('path').join(
|
||||
__dirname,
|
||||
'../../coverage/oidc-client-rx'
|
||||
),
|
||||
subdir: '.',
|
||||
reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'lcov' }],
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
customLaunchers: {
|
||||
ChromeHeadlessNoSandbox: {
|
||||
base: 'ChromeHeadless',
|
||||
flags: ['--no-sandbox'],
|
||||
},
|
||||
},
|
||||
singleRun: false,
|
||||
restartOnFileChange: true,
|
||||
});
|
||||
};
|
3006
package-lock.json
generated
Normal file
3006
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@ -22,9 +22,7 @@
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"files": ["dist"],
|
||||
"scripts": {
|
||||
"build": "rslib build",
|
||||
"dev": "rslib build --watch",
|
||||
@ -39,19 +37,24 @@
|
||||
"dependencies": {
|
||||
"@ngify/http": "^2.0.4",
|
||||
"injection-js": "git+https://github.com/mgechev/injection-js.git#81a10e0",
|
||||
"rxjs": ">=7.4.0"
|
||||
"reflect-metadata": "^0.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rxjs": "^7.4.0||>=8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@evilmartians/lefthook": "^1.0.3",
|
||||
"@playwright/test": "^1.49.1",
|
||||
"@rslib/core": "^0.3.1",
|
||||
"@types/jasmine": "^4.0.0",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^22.10.1",
|
||||
"@vitest/coverage-v8": "^3.0.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"rfc4648": "^1.5.0",
|
||||
"typescript": "^5.7.3",
|
||||
"ultracite": "^4.1.15",
|
||||
"vitest": "^3.0.1"
|
||||
"vitest": "^3.0.1",
|
||||
"rxjs": "^7.4.0"
|
||||
},
|
||||
"keywords": [
|
||||
"rxjs",
|
||||
|
41
pnpm-lock.yaml
generated
41
pnpm-lock.yaml
generated
@ -14,9 +14,9 @@ importers:
|
||||
injection-js:
|
||||
specifier: git+https://github.com/mgechev/injection-js.git#81a10e0
|
||||
version: https://codeload.github.com/mgechev/injection-js/tar.gz/81a10e0
|
||||
rxjs:
|
||||
specifier: '>=7.4.0'
|
||||
version: 7.8.1
|
||||
reflect-metadata:
|
||||
specifier: ^0.2.2
|
||||
version: 0.2.2
|
||||
devDependencies:
|
||||
'@evilmartians/lefthook':
|
||||
specifier: ^1.0.3
|
||||
@ -27,18 +27,24 @@ importers:
|
||||
'@rslib/core':
|
||||
specifier: ^0.3.1
|
||||
version: 0.3.1(typescript@5.7.3)
|
||||
'@types/jasmine':
|
||||
specifier: ^4.0.0
|
||||
version: 4.6.4
|
||||
'@types/lodash-es':
|
||||
specifier: ^4.17.12
|
||||
version: 4.17.12
|
||||
'@types/node':
|
||||
specifier: ^22.10.1
|
||||
version: 22.10.7
|
||||
'@vitest/coverage-v8':
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1(vitest@3.0.1(@types/node@22.10.7))
|
||||
lodash-es:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
rfc4648:
|
||||
specifier: ^1.5.0
|
||||
version: 1.5.4
|
||||
rxjs:
|
||||
specifier: ^7.4.0
|
||||
version: 7.8.1
|
||||
typescript:
|
||||
specifier: ^5.7.3
|
||||
version: 5.7.3
|
||||
@ -469,8 +475,11 @@ packages:
|
||||
'@types/estree@1.0.6':
|
||||
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
|
||||
|
||||
'@types/jasmine@4.6.4':
|
||||
resolution: {integrity: sha512-qCw5sVW+ylTnrEhe5kfX4l6MgU9REXIVDa/lWEcvTOUmd+LqDYwyjovDq+Zk9blElaEHOj1URDQ/djEBVRf+pw==}
|
||||
'@types/lodash-es@4.17.12':
|
||||
resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
|
||||
|
||||
'@types/lodash@4.17.15':
|
||||
resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==}
|
||||
|
||||
'@types/node@22.10.7':
|
||||
resolution: {integrity: sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==}
|
||||
@ -677,6 +686,9 @@ packages:
|
||||
jackspeak@3.4.3:
|
||||
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
|
||||
|
||||
lodash-es@4.17.21:
|
||||
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
|
||||
|
||||
loupe@3.1.2:
|
||||
resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==}
|
||||
|
||||
@ -748,6 +760,9 @@ packages:
|
||||
resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
reflect-metadata@0.2.2:
|
||||
resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==}
|
||||
|
||||
rfc4648@1.5.4:
|
||||
resolution: {integrity: sha512-rRg/6Lb+IGfJqO05HZkN50UtY7K/JhxJag1kP23+zyMfrvoB0B7RWv06MbOzoc79RgCdNTiUaNsTT1AJZ7Z+cg==}
|
||||
|
||||
@ -1244,7 +1259,11 @@ snapshots:
|
||||
|
||||
'@types/estree@1.0.6': {}
|
||||
|
||||
'@types/jasmine@4.6.4': {}
|
||||
'@types/lodash-es@4.17.12':
|
||||
dependencies:
|
||||
'@types/lodash': 4.17.15
|
||||
|
||||
'@types/lodash@4.17.15': {}
|
||||
|
||||
'@types/node@22.10.7':
|
||||
dependencies:
|
||||
@ -1469,6 +1488,8 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@pkgjs/parseargs': 0.11.0
|
||||
|
||||
lodash-es@4.17.21: {}
|
||||
|
||||
loupe@3.1.2: {}
|
||||
|
||||
lru-cache@10.4.3: {}
|
||||
@ -1528,6 +1549,8 @@ snapshots:
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
reflect-metadata@0.2.2: {}
|
||||
|
||||
rfc4648@1.5.4: {}
|
||||
|
||||
rollup@4.30.1:
|
||||
|
@ -1,13 +1,15 @@
|
||||
import { TestBed } from '@/testing/testbed';
|
||||
import {
|
||||
HttpHeaders,
|
||||
provideHttpClient,
|
||||
withInterceptorsFromDi,
|
||||
} from '@angular/common/http';
|
||||
} from '@ngify/http';
|
||||
import {
|
||||
HttpTestingController,
|
||||
provideHttpClientTesting,
|
||||
} from '@angular/common/http/testing';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
} from '@ngify/http/testing';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from './data.service';
|
||||
import { HttpBaseService } from './http-base.service';
|
||||
|
||||
@ -25,9 +27,6 @@ describe('Data Service', () => {
|
||||
provideHttpClientTesting(),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
dataService = TestBed.inject(DataService);
|
||||
httpMock = TestBed.inject(HttpTestingController);
|
||||
});
|
||||
@ -37,7 +36,7 @@ describe('Data Service', () => {
|
||||
});
|
||||
|
||||
describe('get', () => {
|
||||
it('get call sets the accept header', waitForAsync(() => {
|
||||
it('get call sets the accept header', async () => {
|
||||
const url = 'testurl';
|
||||
|
||||
dataService
|
||||
@ -53,9 +52,9 @@ describe('Data Service', () => {
|
||||
req.flush('bodyData');
|
||||
|
||||
httpMock.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('get call with token the accept header and the token', waitForAsync(() => {
|
||||
it('get call with token the accept header and the token', async () => {
|
||||
const url = 'testurl';
|
||||
const token = 'token';
|
||||
|
||||
@ -68,14 +67,14 @@ describe('Data Service', () => {
|
||||
|
||||
expect(req.request.method).toBe('GET');
|
||||
expect(req.request.headers.get('Accept')).toBe('application/json');
|
||||
expect(req.request.headers.get('Authorization')).toBe('Bearer ' + token);
|
||||
expect(req.request.headers.get('Authorization')).toBe(`Bearer ${token}`);
|
||||
|
||||
req.flush('bodyData');
|
||||
|
||||
httpMock.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('call without ngsw-bypass param by default', waitForAsync(() => {
|
||||
it('call without ngsw-bypass param by default', async () => {
|
||||
const url = 'testurl';
|
||||
|
||||
dataService
|
||||
@ -92,9 +91,9 @@ describe('Data Service', () => {
|
||||
req.flush('bodyData');
|
||||
|
||||
httpMock.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('call with ngsw-bypass param', waitForAsync(() => {
|
||||
it('call with ngsw-bypass param', async () => {
|
||||
const url = 'testurl';
|
||||
|
||||
dataService
|
||||
@ -102,7 +101,7 @@ describe('Data Service', () => {
|
||||
.subscribe((data: unknown) => {
|
||||
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.headers.get('Accept')).toBe('application/json');
|
||||
@ -111,11 +110,11 @@ describe('Data Service', () => {
|
||||
req.flush('bodyData');
|
||||
|
||||
httpMock.verify();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('post', () => {
|
||||
it('call sets the accept header when no other params given', waitForAsync(() => {
|
||||
it('call sets the accept header when no other params given', async () => {
|
||||
const url = 'testurl';
|
||||
|
||||
dataService
|
||||
@ -128,18 +127,23 @@ describe('Data Service', () => {
|
||||
|
||||
req.flush('bodyData');
|
||||
|
||||
httpMock.verify();
|
||||
}));
|
||||
await httpMock.verify();
|
||||
});
|
||||
|
||||
it('call sets custom headers ONLY (No ACCEPT header) when custom headers are given', waitForAsync(() => {
|
||||
it('call sets custom headers ONLY (No ACCEPT header) when custom headers are given', async () => {
|
||||
const url = 'testurl';
|
||||
let headers = new HttpHeaders();
|
||||
|
||||
headers = headers.set('X-MyHeader', 'Genesis');
|
||||
|
||||
dataService
|
||||
.post(url, { some: 'thing' }, { configId: 'configId1' }, headers)
|
||||
.subscribe();
|
||||
await lastValueFrom(
|
||||
dataService.post(
|
||||
url,
|
||||
{ some: 'thing' },
|
||||
{ configId: 'configId1' },
|
||||
headers
|
||||
)
|
||||
);
|
||||
const req = httpMock.expectOne(url);
|
||||
|
||||
expect(req.request.method).toBe('POST');
|
||||
@ -149,14 +153,14 @@ describe('Data Service', () => {
|
||||
req.flush('bodyData');
|
||||
|
||||
httpMock.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('call without ngsw-bypass param by default', waitForAsync(() => {
|
||||
it('call without ngsw-bypass param by default', async () => {
|
||||
const url = 'testurl';
|
||||
|
||||
dataService
|
||||
.post(url, { some: 'thing' }, { configId: 'configId1' })
|
||||
.subscribe();
|
||||
await lastValueFrom(
|
||||
dataService.post(url, { some: 'thing' }, { configId: 'configId1' })
|
||||
);
|
||||
const req = httpMock.expectOne(url);
|
||||
|
||||
expect(req.request.method).toBe('POST');
|
||||
@ -166,18 +170,19 @@ describe('Data Service', () => {
|
||||
req.flush('bodyData');
|
||||
|
||||
httpMock.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('call with ngsw-bypass param', waitForAsync(() => {
|
||||
it('call with ngsw-bypass param', async () => {
|
||||
const url = 'testurl';
|
||||
|
||||
dataService
|
||||
.post(
|
||||
await lastValueFrom(
|
||||
dataService.post(
|
||||
url,
|
||||
{ some: 'thing' },
|
||||
{ configId: 'configId1', ngswBypass: true }
|
||||
)
|
||||
.subscribe();
|
||||
);
|
||||
// biome-ignore lint/style/useTemplate: <explanation>
|
||||
const req = httpMock.expectOne(url + '?ngsw-bypass=');
|
||||
|
||||
expect(req.request.method).toBe('POST');
|
||||
@ -187,6 +192,6 @@ describe('Data Service', () => {
|
||||
req.flush('bodyData');
|
||||
|
||||
httpMock.verify();
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { PassedInitialConfig, createStaticLoader } from './auth-config';
|
||||
import { type PassedInitialConfig, createStaticLoader } from './auth-config';
|
||||
|
||||
describe('AuthConfig', () => {
|
||||
describe('createStaticLoader', () => {
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { InjectionToken, Provider } from 'injection-js';
|
||||
import { InjectionToken, type Provider } from 'injection-js';
|
||||
import {
|
||||
StsConfigLoader,
|
||||
type StsConfigLoader,
|
||||
StsConfigStaticLoader,
|
||||
} from './config/loader/config-loader';
|
||||
import { OpenIdConfiguration } from './config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from './config/openid-configuration';
|
||||
|
||||
export interface PassedInitialConfig {
|
||||
config?: OpenIdConfiguration | OpenIdConfiguration[];
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { Observable } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { EventTypes } from '../public-events/event-types';
|
||||
import { PublicEventsService } from '../public-events/public-events.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { PlatformProvider } from '../utils/platform-provider/platform.provider';
|
||||
import { TokenValidationService } from '../validation/token-validation.service';
|
||||
import { ValidationResult } from '../validation/validation-result';
|
||||
import type { ValidationResult } from '../validation/validation-result';
|
||||
import { AuthStateService } from './auth-state.service';
|
||||
|
||||
describe('Auth State Service', () => {
|
||||
@ -27,9 +28,6 @@ describe('Auth State Service', () => {
|
||||
mockProvider(StoragePersistenceService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
eventsService = TestBed.inject(PublicEventsService);
|
||||
@ -41,12 +39,12 @@ describe('Auth State Service', () => {
|
||||
});
|
||||
|
||||
it('public authorize$ is observable$', () => {
|
||||
expect(authStateService.authenticated$).toEqual(jasmine.any(Observable));
|
||||
expect(authStateService.authenticated$).toBeInstanceOf(Observable);
|
||||
});
|
||||
|
||||
describe('setAuthorizedAndFireEvent', () => {
|
||||
it('throws correct event with single config', () => {
|
||||
const spy = spyOn(
|
||||
const spy = vi.spyOn(
|
||||
(authStateService as any).authenticatedInternal$,
|
||||
'next'
|
||||
);
|
||||
@ -55,7 +53,7 @@ describe('Auth State Service', () => {
|
||||
{ configId: 'configId1' },
|
||||
]);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith({
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
allConfigsAuthenticated: [
|
||||
{ configId: 'configId1', isAuthenticated: true },
|
||||
@ -64,7 +62,7 @@ describe('Auth State Service', () => {
|
||||
});
|
||||
|
||||
it('throws correct event with multiple configs', () => {
|
||||
const spy = spyOn(
|
||||
const spy = vi.spyOn(
|
||||
(authStateService as any).authenticatedInternal$,
|
||||
'next'
|
||||
);
|
||||
@ -74,7 +72,7 @@ describe('Auth State Service', () => {
|
||||
{ configId: 'configId2' },
|
||||
]);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith({
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
allConfigsAuthenticated: [
|
||||
{ configId: 'configId1', isAuthenticated: false },
|
||||
@ -86,26 +84,34 @@ describe('Auth State Service', () => {
|
||||
it('throws correct event with multiple configs, one is authenticated', () => {
|
||||
const allConfigs = [{ configId: 'configId1' }, { configId: 'configId2' }];
|
||||
|
||||
spyOn(storagePersistenceService, 'getAccessToken')
|
||||
.withArgs(allConfigs[0])
|
||||
.and.returnValue('someAccessToken')
|
||||
.withArgs(allConfigs[1])
|
||||
.and.returnValue('');
|
||||
mockImplementationWhenArgsEqual(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken'),
|
||||
[allConfigs[0]!],
|
||||
() => 'someAccessToken'
|
||||
),
|
||||
[allConfigs[1]!],
|
||||
() => ''
|
||||
);
|
||||
|
||||
spyOn(storagePersistenceService, 'getIdToken')
|
||||
.withArgs(allConfigs[0])
|
||||
.and.returnValue('someIdToken')
|
||||
.withArgs(allConfigs[1])
|
||||
.and.returnValue('');
|
||||
mockImplementationWhenArgsEqual(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken'),
|
||||
[allConfigs[0]!],
|
||||
() => 'someIdToken'
|
||||
),
|
||||
[allConfigs[1]!],
|
||||
() => ''
|
||||
);
|
||||
|
||||
const spy = spyOn(
|
||||
const spy = vi.spyOn(
|
||||
(authStateService as any).authenticatedInternal$,
|
||||
'next'
|
||||
);
|
||||
|
||||
authStateService.setAuthenticatedAndFireEvent(allConfigs);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith({
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
allConfigsAuthenticated: [
|
||||
{ configId: 'configId1', isAuthenticated: true },
|
||||
@ -117,17 +123,20 @@ describe('Auth State Service', () => {
|
||||
|
||||
describe('setUnauthorizedAndFireEvent', () => {
|
||||
it('persist AuthState In Storage', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'resetAuthStateInStorage');
|
||||
const spy = vi.spyOn(
|
||||
storagePersistenceService,
|
||||
'resetAuthStateInStorage'
|
||||
);
|
||||
|
||||
authStateService.setUnauthenticatedAndFireEvent(
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
|
||||
});
|
||||
|
||||
it('throws correct event with single config', () => {
|
||||
const spy = spyOn(
|
||||
const spy = vi.spyOn(
|
||||
(authStateService as any).authenticatedInternal$,
|
||||
'next'
|
||||
);
|
||||
@ -137,7 +146,7 @@ describe('Auth State Service', () => {
|
||||
[{ configId: 'configId1' }]
|
||||
);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith({
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
allConfigsAuthenticated: [
|
||||
{ configId: 'configId1', isAuthenticated: false },
|
||||
@ -146,7 +155,7 @@ describe('Auth State Service', () => {
|
||||
});
|
||||
|
||||
it('throws correct event with multiple configs', () => {
|
||||
const spy = spyOn(
|
||||
const spy = vi.spyOn(
|
||||
(authStateService as any).authenticatedInternal$,
|
||||
'next'
|
||||
);
|
||||
@ -156,7 +165,7 @@ describe('Auth State Service', () => {
|
||||
[{ configId: 'configId1' }, { configId: 'configId2' }]
|
||||
);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith({
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
allConfigsAuthenticated: [
|
||||
{ configId: 'configId1', isAuthenticated: false },
|
||||
@ -166,19 +175,27 @@ describe('Auth State Service', () => {
|
||||
});
|
||||
|
||||
it('throws correct event with multiple configs, one is authenticated', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken')
|
||||
.withArgs({ configId: 'configId1' })
|
||||
.and.returnValue('someAccessToken')
|
||||
.withArgs({ configId: 'configId2' })
|
||||
.and.returnValue('');
|
||||
mockImplementationWhenArgsEqual(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken'),
|
||||
[{ configId: 'configId1' }],
|
||||
() => 'someAccessToken'
|
||||
),
|
||||
[{ configId: 'configId2' }],
|
||||
() => ''
|
||||
);
|
||||
|
||||
spyOn(storagePersistenceService, 'getIdToken')
|
||||
.withArgs({ configId: 'configId1' })
|
||||
.and.returnValue('someIdToken')
|
||||
.withArgs({ configId: 'configId2' })
|
||||
.and.returnValue('');
|
||||
mockImplementationWhenArgsEqual(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken'),
|
||||
[{ configId: 'configId1' }],
|
||||
() => 'someIdToken'
|
||||
),
|
||||
[{ configId: 'configId2' }],
|
||||
() => ''
|
||||
);
|
||||
|
||||
const spy = spyOn(
|
||||
const spy = vi.spyOn(
|
||||
(authStateService as any).authenticatedInternal$,
|
||||
'next'
|
||||
);
|
||||
@ -188,7 +205,7 @@ describe('Auth State Service', () => {
|
||||
[{ configId: 'configId1' }, { configId: 'configId2' }]
|
||||
);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith({
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
allConfigsAuthenticated: [
|
||||
{ configId: 'configId1', isAuthenticated: true },
|
||||
@ -200,24 +217,27 @@ describe('Auth State Service', () => {
|
||||
|
||||
describe('updateAndPublishAuthState', () => {
|
||||
it('calls eventsService', () => {
|
||||
spyOn(eventsService, 'fireEvent');
|
||||
vi.spyOn(eventsService, 'fireEvent');
|
||||
|
||||
authStateService.updateAndPublishAuthState({
|
||||
const arg = {
|
||||
isAuthenticated: false,
|
||||
isRenewProcess: false,
|
||||
validationResult: {} as ValidationResult,
|
||||
});
|
||||
};
|
||||
|
||||
expect(eventsService.fireEvent).toHaveBeenCalledOnceWith(
|
||||
authStateService.updateAndPublishAuthState(arg);
|
||||
|
||||
expect(eventsService.fireEvent).toHaveBeenCalledOnce();
|
||||
expect(eventsService.fireEvent).toHaveBeenCalledExactlyOnceWith(
|
||||
EventTypes.NewAuthenticationResult,
|
||||
jasmine.any(Object)
|
||||
arg
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setAuthorizationData', () => {
|
||||
it('stores accessToken', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'write');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
const authResult = {
|
||||
id_token: 'idtoken',
|
||||
access_token: 'accesstoken',
|
||||
@ -237,18 +257,18 @@ describe('Auth State Service', () => {
|
||||
[{ configId: 'configId1' }]
|
||||
);
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
expect(spy.calls.allArgs()).toEqual([
|
||||
expect(spy).toHaveBeenCalledWith([
|
||||
['authzData', 'accesstoken', { configId: 'configId1' }],
|
||||
[
|
||||
'access_token_expires_at',
|
||||
jasmine.any(Number),
|
||||
expect.any(Number),
|
||||
{ configId: 'configId1' },
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not crash and store accessToken when authResult is null', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'write');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
const authResult = null;
|
||||
|
||||
authStateService.setAuthorizationData(
|
||||
@ -262,7 +282,7 @@ describe('Auth State Service', () => {
|
||||
});
|
||||
|
||||
it('calls setAuthenticatedAndFireEvent() method', () => {
|
||||
const spy = spyOn(authStateService, 'setAuthenticatedAndFireEvent');
|
||||
const spy = vi.spyOn(authStateService, 'setAuthenticatedAndFireEvent');
|
||||
const authResult = {
|
||||
id_token: 'idtoken',
|
||||
access_token: 'accesstoken',
|
||||
@ -288,28 +308,29 @@ describe('Auth State Service', () => {
|
||||
|
||||
describe('getAccessToken', () => {
|
||||
it('isAuthorized is false returns null', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
|
||||
const result = authStateService.getAccessToken({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('returns false if storagePersistenceService returns something falsy but authorized', () => {
|
||||
spyOn(authStateService, 'isAuthenticated').and.returnValue(true);
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
|
||||
vi.spyOn(authStateService, 'isAuthenticated').mockReturnValue(true);
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
|
||||
const result = authStateService.getAccessToken({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('isAuthorized is true returns decodeURIComponent(token)', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
'HenloLegger'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'HenloFuriend'
|
||||
);
|
||||
|
||||
const result = authStateService.getAccessToken({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBe(decodeURIComponent('HenloLegger'));
|
||||
@ -318,12 +339,14 @@ describe('Auth State Service', () => {
|
||||
|
||||
describe('getAuthenticationResult', () => {
|
||||
it('isAuthorized is false returns null', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
|
||||
|
||||
spyOn(storagePersistenceService, 'getAuthenticationResult')
|
||||
.withArgs({ configId: 'configId1' })
|
||||
.and.returnValue({});
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'getAuthenticationResult'),
|
||||
[{ configId: 'configId1' }],
|
||||
() => ({})
|
||||
);
|
||||
|
||||
const result = authStateService.getAuthenticationResult({
|
||||
configId: 'configId1',
|
||||
@ -333,10 +356,13 @@ describe('Auth State Service', () => {
|
||||
});
|
||||
|
||||
it('returns false if storagePersistenceService returns something falsy but authorized', () => {
|
||||
spyOn(authStateService, 'isAuthenticated').and.returnValue(true);
|
||||
spyOn(storagePersistenceService, 'getAuthenticationResult')
|
||||
.withArgs({ configId: 'configId1' })
|
||||
.and.returnValue({});
|
||||
vi.spyOn(authStateService, 'isAuthenticated').mockReturnValue(true);
|
||||
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'getAuthenticationResult'),
|
||||
[{ configId: 'configId1' }],
|
||||
() => ({})
|
||||
);
|
||||
|
||||
const result = authStateService.getAuthenticationResult({
|
||||
configId: 'configId1',
|
||||
@ -346,15 +372,18 @@ describe('Auth State Service', () => {
|
||||
});
|
||||
|
||||
it('isAuthorized is true returns object', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
'HenloLegger'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'HenloFuriend'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getAuthenticationResult')
|
||||
.withArgs({ configId: 'configId1' })
|
||||
.and.returnValue({ scope: 'HenloFuriend' });
|
||||
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'getAuthenticationResult'),
|
||||
[{ configId: 'configId1' }],
|
||||
() => ({ scope: 'HenloFuriend' })
|
||||
);
|
||||
|
||||
const result = authStateService.getAuthenticationResult({
|
||||
configId: 'configId1',
|
||||
@ -366,18 +395,18 @@ describe('Auth State Service', () => {
|
||||
|
||||
describe('getIdToken', () => {
|
||||
it('isAuthorized is false returns null', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
|
||||
const result = authStateService.getIdToken({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBe('');
|
||||
});
|
||||
|
||||
it('isAuthorized is true returns decodeURIComponent(token)', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
'HenloLegger'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'HenloFuriend'
|
||||
);
|
||||
const result = authStateService.getIdToken({ configId: 'configId1' });
|
||||
@ -388,8 +417,8 @@ describe('Auth State Service', () => {
|
||||
|
||||
describe('getRefreshToken', () => {
|
||||
it('isAuthorized is false returns null', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
|
||||
const result = authStateService.getRefreshToken({
|
||||
configId: 'configId1',
|
||||
});
|
||||
@ -398,13 +427,13 @@ describe('Auth State Service', () => {
|
||||
});
|
||||
|
||||
it('isAuthorized is true returns decodeURIComponent(token)', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
'HenloLegger'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'HenloFuriend'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
'HenloRefreshLegger'
|
||||
);
|
||||
const result = authStateService.getRefreshToken({
|
||||
@ -417,105 +446,105 @@ describe('Auth State Service', () => {
|
||||
|
||||
describe('areAuthStorageTokensValid', () => {
|
||||
it('isAuthorized is false returns false', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue('');
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue('');
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue('');
|
||||
const result = authStateService.areAuthStorageTokensValid({
|
||||
configId: 'configId1',
|
||||
});
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('isAuthorized is true and id_token is expired returns true', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
'HenloLegger'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'HenloFuriend'
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authStateService as any,
|
||||
'hasIdTokenExpiredAndRenewCheckIsEnabled'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authStateService as any,
|
||||
'hasAccessTokenExpiredIfExpiryExists'
|
||||
).and.returnValue(false);
|
||||
).mockReturnValue(false);
|
||||
const result = authStateService.areAuthStorageTokensValid({
|
||||
configId: 'configId1',
|
||||
});
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('isAuthorized is true and access_token is expired returns true', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
'HenloLegger'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'HenloFuriend'
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authStateService as any,
|
||||
'hasIdTokenExpiredAndRenewCheckIsEnabled'
|
||||
).and.returnValue(false);
|
||||
spyOn(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
authStateService as any,
|
||||
'hasAccessTokenExpiredIfExpiryExists'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const result = authStateService.areAuthStorageTokensValid({
|
||||
configId: 'configId1',
|
||||
});
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('isAuthorized is true and id_token is not expired returns true', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
'HenloLegger'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'HenloFuriend'
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authStateService as any,
|
||||
'hasIdTokenExpiredAndRenewCheckIsEnabled'
|
||||
).and.returnValue(false);
|
||||
spyOn(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
authStateService as any,
|
||||
'hasAccessTokenExpiredIfExpiryExists'
|
||||
).and.returnValue(false);
|
||||
).mockReturnValue(false);
|
||||
const result = authStateService.areAuthStorageTokensValid({
|
||||
configId: 'configId1',
|
||||
});
|
||||
|
||||
expect(result).toBeTrue();
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('authState is AuthorizedState.Authorized and id_token is not expired fires event', () => {
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
'HenloLegger'
|
||||
);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'HenloFuriend'
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authStateService as any,
|
||||
'hasIdTokenExpiredAndRenewCheckIsEnabled'
|
||||
).and.returnValue(false);
|
||||
spyOn(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
authStateService as any,
|
||||
'hasAccessTokenExpiredIfExpiryExists'
|
||||
).and.returnValue(false);
|
||||
).mockReturnValue(false);
|
||||
const result = authStateService.areAuthStorageTokensValid({
|
||||
configId: 'configId1',
|
||||
});
|
||||
|
||||
expect(result).toBeTrue();
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@ -527,56 +556,65 @@ describe('Auth State Service', () => {
|
||||
triggerRefreshWhenIdTokenExpired: true,
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'getIdToken')
|
||||
.withArgs(config)
|
||||
.and.returnValue('idToken');
|
||||
const spy = spyOn(
|
||||
tokenValidationService,
|
||||
'hasIdTokenExpired'
|
||||
).and.callFake((_a, _b) => true);
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken'),
|
||||
[config],
|
||||
() => 'idToken'
|
||||
);
|
||||
const spy = vi
|
||||
.spyOn(tokenValidationService, 'hasIdTokenExpired')
|
||||
.mockImplementation((_a, _b) => true);
|
||||
|
||||
authStateService.hasIdTokenExpiredAndRenewCheckIsEnabled(config);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('idToken', config, 30);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('idToken', config, 30);
|
||||
});
|
||||
|
||||
it('fires event if idToken is expired', () => {
|
||||
spyOn(tokenValidationService, 'hasIdTokenExpired').and.callFake(
|
||||
vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockImplementation(
|
||||
(_a, _b) => true
|
||||
);
|
||||
|
||||
const spy = spyOn(eventsService, 'fireEvent');
|
||||
const spy = vi.spyOn(eventsService, 'fireEvent');
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
renewTimeBeforeTokenExpiresInSeconds: 30,
|
||||
triggerRefreshWhenIdTokenExpired: true,
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authnResult', config)
|
||||
.and.returnValue('idToken');
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authnResult', config],
|
||||
() => 'idToken'
|
||||
);
|
||||
|
||||
const result =
|
||||
authStateService.hasIdTokenExpiredAndRenewCheckIsEnabled(config);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(spy).toHaveBeenCalledOnceWith(EventTypes.IdTokenExpired, true);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
EventTypes.IdTokenExpired,
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('does NOT fire event if idToken is NOT expired', () => {
|
||||
spyOn(tokenValidationService, 'hasIdTokenExpired').and.callFake(
|
||||
vi.spyOn(tokenValidationService, 'hasIdTokenExpired').mockImplementation(
|
||||
(_a, _b) => false
|
||||
);
|
||||
|
||||
const spy = spyOn(eventsService, 'fireEvent');
|
||||
const spy = vi.spyOn(eventsService, 'fireEvent');
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
renewTimeBeforeTokenExpiresInSeconds: 30,
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authnResult', config)
|
||||
.and.returnValue('idToken');
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authnResult', config],
|
||||
() => 'idToken'
|
||||
);
|
||||
|
||||
const result =
|
||||
authStateService.hasIdTokenExpiredAndRenewCheckIsEnabled(config);
|
||||
|
||||
@ -595,41 +633,45 @@ describe('Auth State Service', () => {
|
||||
renewTimeBeforeTokenExpiresInSeconds: 5,
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('access_token_expires_at', config)
|
||||
.and.returnValue(date);
|
||||
const spy = spyOn(
|
||||
tokenValidationService,
|
||||
'validateAccessTokenNotExpired'
|
||||
).and.returnValue(validateAccessTokenNotExpiredResult);
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['access_token_expires_at', config],
|
||||
() => date
|
||||
);
|
||||
const spy = vi
|
||||
.spyOn(tokenValidationService, 'validateAccessTokenNotExpired')
|
||||
.mockReturnValue(validateAccessTokenNotExpiredResult);
|
||||
const result =
|
||||
authStateService.hasAccessTokenExpiredIfExpiryExists(config);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith(date, config, 5);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(date, config, 5);
|
||||
expect(result).toEqual(expectedResult);
|
||||
});
|
||||
|
||||
it('throws event when token is expired', () => {
|
||||
const validateAccessTokenNotExpiredResult = false;
|
||||
const expectedResult = !validateAccessTokenNotExpiredResult;
|
||||
// spyOn(configurationProvider, 'getOpenIDConfiguration').and.returnValue({ renewTimeBeforeTokenExpiresInSeconds: 5 });
|
||||
// vi.spyOn(configurationProvider, 'getOpenIDConfiguration').mockReturnValue({ renewTimeBeforeTokenExpiresInSeconds: 5 });
|
||||
const date = new Date(new Date().toUTCString());
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
renewTimeBeforeTokenExpiresInSeconds: 5,
|
||||
};
|
||||
|
||||
spyOn(eventsService, 'fireEvent');
|
||||
vi.spyOn(eventsService, 'fireEvent');
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('access_token_expires_at', config)
|
||||
.and.returnValue(date);
|
||||
spyOn(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['access_token_expires_at', config],
|
||||
() => date
|
||||
);
|
||||
|
||||
vi.spyOn(
|
||||
tokenValidationService,
|
||||
'validateAccessTokenNotExpired'
|
||||
).and.returnValue(validateAccessTokenNotExpiredResult);
|
||||
).mockReturnValue(validateAccessTokenNotExpiredResult);
|
||||
authStateService.hasAccessTokenExpiredIfExpiryExists(config);
|
||||
expect(eventsService.fireEvent).toHaveBeenCalledOnceWith(
|
||||
expect(eventsService.fireEvent).toHaveBeenCalledExactlyOnceWith(
|
||||
EventTypes.TokenExpired,
|
||||
expectedResult
|
||||
);
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { BehaviorSubject, Observable, throwError } from 'rxjs';
|
||||
import { BehaviorSubject, type Observable, throwError } from 'rxjs';
|
||||
import { distinctUntilChanged } from 'rxjs/operators';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { AuthResult } from '../flows/callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { AuthResult } from '../flows/callback-context';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { EventTypes } from '../public-events/event-types';
|
||||
import { PublicEventsService } from '../public-events/public-events.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { TokenValidationService } from '../validation/token-validation.service';
|
||||
import { AuthenticatedResult } from './auth-result';
|
||||
import { AuthStateResult } from './auth-state';
|
||||
import type { AuthenticatedResult } from './auth-result';
|
||||
import type { AuthStateResult } from './auth-state';
|
||||
|
||||
const DEFAULT_AUTHRESULT = {
|
||||
isAuthenticated: false,
|
||||
@ -293,7 +293,7 @@ export class AuthStateService {
|
||||
};
|
||||
}
|
||||
|
||||
return this.checkAllConfigsIfTheyAreAuthenticated(allConfigs);
|
||||
return this.checkallConfigsIfTheyAreAuthenticated(allConfigs);
|
||||
}
|
||||
|
||||
private composeUnAuthenticatedResult(
|
||||
@ -310,10 +310,10 @@ export class AuthStateService {
|
||||
};
|
||||
}
|
||||
|
||||
return this.checkAllConfigsIfTheyAreAuthenticated(allConfigs);
|
||||
return this.checkallConfigsIfTheyAreAuthenticated(allConfigs);
|
||||
}
|
||||
|
||||
private checkAllConfigsIfTheyAreAuthenticated(
|
||||
private checkallConfigsIfTheyAreAuthenticated(
|
||||
allConfigs: OpenIdConfiguration[]
|
||||
): AuthenticatedResult {
|
||||
const allConfigsAuthenticated = allConfigs.map((config) => ({
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,15 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { forkJoin, Observable, of, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, forkJoin, of, throwError } from 'rxjs';
|
||||
import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { AutoLoginService } from '../auto-login/auto-login.service';
|
||||
import { CallbackService } from '../callback/callback.service';
|
||||
import { PeriodicallyTokenCheckService } from '../callback/periodically-token-check.service';
|
||||
import { RefreshSessionService } from '../callback/refresh-session.service';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CheckSessionService } from '../iframe/check-session.service';
|
||||
import { SilentRenewService } from '../iframe/silent-renew.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { LoginResponse } from '../login/login-response';
|
||||
import type { LoginResponse } from '../login/login-response';
|
||||
import { PopUpService } from '../login/popup/popup.service';
|
||||
import { EventTypes } from '../public-events/event-types';
|
||||
import { PublicEventsService } from '../public-events/public-events.service';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { PASSED_CONFIG } from './auth-config';
|
||||
import { AuthModule } from './auth.module';
|
||||
import { ConfigurationService } from './config/config.service';
|
||||
@ -9,19 +9,20 @@ import {
|
||||
StsConfigLoader,
|
||||
StsConfigStaticLoader,
|
||||
} from './config/loader/config-loader';
|
||||
import { mockProvider } from './testing/mock';
|
||||
|
||||
describe('AuthModule', () => {
|
||||
describe('APP_CONFIG', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AuthModule.forRoot({ config: { authority: 'something' } })],
|
||||
providers: [mockProvider(ConfigurationService)],
|
||||
}).compileComponents();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(AuthModule).toBeDefined();
|
||||
expect(AuthModule.forRoot({})).toBeDefined();
|
||||
expect(new AuthModule()).toBeDefined();
|
||||
});
|
||||
|
||||
it('should provide config', () => {
|
||||
@ -38,8 +39,8 @@ describe('AuthModule', () => {
|
||||
});
|
||||
|
||||
describe('StsConfigHttpLoader', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AuthModule.forRoot({
|
||||
loader: {
|
||||
@ -50,7 +51,7 @@ describe('AuthModule', () => {
|
||||
],
|
||||
providers: [mockProvider(ConfigurationService)],
|
||||
}).compileComponents();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should create StsConfigStaticLoader if config is passed', () => {
|
||||
const configLoader = TestBed.inject(StsConfigLoader);
|
||||
|
@ -1,25 +1,41 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
provideHttpClient,
|
||||
withInterceptorsFromDi,
|
||||
} from '@ngify/http';
|
||||
import { ModuleWithProviders, NgModule } from 'injection-js';
|
||||
import { PassedInitialConfig } from './auth-config';
|
||||
type InjectionToken,
|
||||
Injector,
|
||||
ReflectiveInjector,
|
||||
type Type,
|
||||
} from 'injection-js';
|
||||
import type { PassedInitialConfig } from './auth-config';
|
||||
import type { Module } from './injection';
|
||||
import { _provideAuth } from './provide-auth';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
exports: [],
|
||||
imports: [CommonModule],
|
||||
providers: [provideHttpClient(withInterceptorsFromDi())],
|
||||
})
|
||||
export class AuthModule {
|
||||
static forRoot(
|
||||
passedConfig: PassedInitialConfig
|
||||
): ModuleWithProviders<AuthModule> {
|
||||
return {
|
||||
ngModule: AuthModule,
|
||||
providers: [..._provideAuth(passedConfig)],
|
||||
};
|
||||
export interface AuthModuleOptions {
|
||||
passedConfig: PassedInitialConfig;
|
||||
parentInjector?: ReflectiveInjector;
|
||||
}
|
||||
|
||||
export class AuthModule extends Injector {
|
||||
passedConfig: PassedInitialConfig;
|
||||
injector: ReflectiveInjector;
|
||||
parentInjector?: Injector;
|
||||
|
||||
constructor(passedConfig?: PassedInitialConfig, parentInjector?: Injector) {
|
||||
super();
|
||||
this.passedConfig = passedConfig ?? {};
|
||||
this.parentInjector = parentInjector;
|
||||
this.injector = ReflectiveInjector.resolveAndCreate(
|
||||
[..._provideAuth(this.passedConfig)],
|
||||
this.parentInjector
|
||||
);
|
||||
}
|
||||
|
||||
static forRoot(passedConfig?: PassedInitialConfig): Module {
|
||||
return (parentInjector?: Injector) =>
|
||||
new AuthModule(passedConfig, parentInjector);
|
||||
}
|
||||
|
||||
get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: T): T;
|
||||
get(token: any, notFoundValue?: any);
|
||||
get(token: unknown, notFoundValue?: unknown): any {
|
||||
return this.injector.get(token, notFoundValue);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, mockRouterProvider } from '@/testing';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
Router,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
AbstractRouter,
|
||||
type ActivatedRouteSnapshot,
|
||||
type RouterStateSnapshot,
|
||||
} from 'oidc-client-rx';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { CheckAuthService } from '../auth-state/check-auth.service';
|
||||
import { ConfigurationService } from '../config/config.service';
|
||||
import { LoginService } from '../login/login.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import {
|
||||
AutoLoginPartialRoutesGuard,
|
||||
autoLoginPartialRoutesGuard,
|
||||
@ -19,11 +19,12 @@ import {
|
||||
} from './auto-login-partial-routes.guard';
|
||||
import { AutoLoginService } from './auto-login.service';
|
||||
|
||||
describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
describe('AutoLoginPartialRoutesGuard', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [RouterTestingModule],
|
||||
imports: [],
|
||||
providers: [
|
||||
mockRouterProvider(),
|
||||
AutoLoginService,
|
||||
mockProvider(AuthStateService),
|
||||
mockProvider(LoginService),
|
||||
@ -41,7 +42,7 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
let storagePersistenceService: StoragePersistenceService;
|
||||
let configurationService: ConfigurationService;
|
||||
let autoLoginService: AutoLoginService;
|
||||
let router: Router;
|
||||
let router: AbstractRouter;
|
||||
|
||||
beforeEach(() => {
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@ -49,15 +50,16 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
configurationService = TestBed.inject(ConfigurationService);
|
||||
|
||||
spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
|
||||
vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
|
||||
of({ configId: 'configId1' })
|
||||
);
|
||||
|
||||
guard = TestBed.inject(AutoLoginPartialRoutesGuard);
|
||||
autoLoginService = TestBed.inject(AutoLoginService);
|
||||
router = TestBed.inject(Router);
|
||||
router = TestBed.inject(AbstractRouter);
|
||||
});
|
||||
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
|
||||
afterEach(() => {
|
||||
storagePersistenceService.clear({});
|
||||
});
|
||||
@ -67,19 +69,19 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
});
|
||||
|
||||
describe('canActivate', () => {
|
||||
it('should save current route and call `login` if not authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should save current route and call `login` if not authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
guard
|
||||
.canActivate(
|
||||
@ -87,32 +89,32 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
{ url: 'some-url1' } as RouterStateSnapshot
|
||||
)
|
||||
.subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'some-url1'
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith({
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(
|
||||
checkSavedRedirectRouteAndNavigateSpy
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should save current route and call `login` if not authenticated already and add custom params', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should save current route and call `login` if not authenticated already and add custom params', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
guard
|
||||
.canActivate(
|
||||
@ -120,11 +122,11 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
{ url: 'some-url1' } as RouterStateSnapshot
|
||||
)
|
||||
.subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'some-url1'
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith(
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
{ customParams: { custom: 'param' } }
|
||||
);
|
||||
@ -132,21 +134,21 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
checkSavedRedirectRouteAndNavigateSpy
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
guard
|
||||
.canActivate(
|
||||
@ -158,25 +160,25 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
expect(loginSpy).not.toHaveBeenCalled();
|
||||
expect(
|
||||
checkSavedRedirectRouteAndNavigateSpy
|
||||
).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('canActivateChild', () => {
|
||||
it('should save current route and call `login` if not authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should save current route and call `login` if not authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
guard
|
||||
.canActivateChild(
|
||||
@ -184,32 +186,32 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
{ url: 'some-url1' } as RouterStateSnapshot
|
||||
)
|
||||
.subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'some-url1'
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith({
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(
|
||||
checkSavedRedirectRouteAndNavigateSpy
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should save current route and call `login` if not authenticated already with custom params', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should save current route and call `login` if not authenticated already with custom params', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
guard
|
||||
.canActivateChild(
|
||||
@ -217,11 +219,11 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
{ url: 'some-url1' } as RouterStateSnapshot
|
||||
)
|
||||
.subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'some-url1'
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith(
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
{ customParams: { custom: 'param' } }
|
||||
);
|
||||
@ -229,21 +231,21 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
checkSavedRedirectRouteAndNavigateSpy
|
||||
).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
guard
|
||||
.canActivateChild(
|
||||
@ -255,51 +257,53 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
expect(loginSpy).not.toHaveBeenCalled();
|
||||
expect(
|
||||
checkSavedRedirectRouteAndNavigateSpy
|
||||
).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('canLoad', () => {
|
||||
it('should save current route (empty) and call `login` if not authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should save current route (empty) and call `login` if not authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
guard.canLoad().subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
''
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should save current route (with router extractedUrl) and call `login` if not authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should save current route (with router extractedUrl) and call `login` if not authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
spyOn(router, 'getCurrentNavigation').and.returnValue({
|
||||
vi.spyOn(router, 'getCurrentNavigation').mockReturnValue({
|
||||
extractedUrl: router.parseUrl(
|
||||
'some-url12/with/some-param?queryParam=true'
|
||||
),
|
||||
@ -311,37 +315,39 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
});
|
||||
|
||||
guard.canLoad().subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'some-url12/with/some-param?queryParam=true'
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
guard.canLoad().subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).not.toHaveBeenCalled();
|
||||
expect(loginSpy).not.toHaveBeenCalled();
|
||||
expect(
|
||||
checkSavedRedirectRouteAndNavigateSpy
|
||||
).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -352,7 +358,7 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
let storagePersistenceService: StoragePersistenceService;
|
||||
let configurationService: ConfigurationService;
|
||||
let autoLoginService: AutoLoginService;
|
||||
let router: Router;
|
||||
let router: AbstractRouter;
|
||||
|
||||
beforeEach(() => {
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@ -360,48 +366,52 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
configurationService = TestBed.inject(ConfigurationService);
|
||||
|
||||
spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
|
||||
of({ configId: 'configId1' })
|
||||
);
|
||||
vi.spyOn(
|
||||
configurationService,
|
||||
'getOpenIDConfiguration'
|
||||
).mockReturnValue(of({ configId: 'configId1' }));
|
||||
|
||||
autoLoginService = TestBed.inject(AutoLoginService);
|
||||
router = TestBed.inject(Router);
|
||||
router = TestBed.inject(AbstractRouter);
|
||||
});
|
||||
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
|
||||
afterEach(() => {
|
||||
storagePersistenceService.clear({});
|
||||
});
|
||||
|
||||
it('should save current route (empty) and call `login` if not authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should save current route (empty) and call `login` if not authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
const guard$ = TestBed.runInInjectionContext(
|
||||
autoLoginPartialRoutesGuard
|
||||
);
|
||||
|
||||
guard$.subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
''
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should save current route (with router extractedUrl) and call `login` if not authenticated already', waitForAsync(() => {
|
||||
spyOn(router, 'getCurrentNavigation').and.returnValue({
|
||||
it('should save current route (with router extractedUrl) and call `login` if not authenticated already', async () => {
|
||||
vi.spyOn(router, 'getCurrentNavigation').mockReturnValue({
|
||||
extractedUrl: router.parseUrl(
|
||||
'some-url12/with/some-param?queryParam=true'
|
||||
),
|
||||
@ -412,46 +422,48 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
trigger: 'imperative',
|
||||
});
|
||||
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
const guard$ = TestBed.runInInjectionContext(
|
||||
autoLoginPartialRoutesGuard
|
||||
);
|
||||
|
||||
guard$.subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'some-url12/with/some-param?queryParam=true'
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should save current route and call `login` if not authenticated already and add custom params', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should save current route and call `login` if not authenticated already and add custom params', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
const guard$ = TestBed.runInInjectionContext(() =>
|
||||
autoLoginPartialRoutesGuard({
|
||||
@ -460,31 +472,31 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
);
|
||||
|
||||
guard$.subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
''
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith(
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
{ customParams: { custom: 'param' } }
|
||||
);
|
||||
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should call `checkSavedRedirectRouteAndNavigate` if authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
const guard$ = TestBed.runInInjectionContext(
|
||||
autoLoginPartialRoutesGuard
|
||||
@ -495,9 +507,9 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
expect(loginSpy).not.toHaveBeenCalled();
|
||||
expect(
|
||||
checkSavedRedirectRouteAndNavigateSpy
|
||||
).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
).toHaveBeenCalledExactlyOnceWith({ configId: 'configId1' });
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('autoLoginPartialRoutesGuardWithConfig', () => {
|
||||
@ -513,44 +525,48 @@ describe(`AutoLoginPartialRoutesGuard`, () => {
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
configurationService = TestBed.inject(ConfigurationService);
|
||||
|
||||
spyOn(configurationService, 'getOpenIDConfiguration').and.callFake(
|
||||
(configId) => of({ configId })
|
||||
);
|
||||
vi.spyOn(
|
||||
configurationService,
|
||||
'getOpenIDConfiguration'
|
||||
).mockImplementation((configId) => of({ configId }));
|
||||
|
||||
autoLoginService = TestBed.inject(AutoLoginService);
|
||||
});
|
||||
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
|
||||
afterEach(() => {
|
||||
storagePersistenceService.clear({});
|
||||
});
|
||||
|
||||
it('should save current route (empty) and call `login` if not authenticated already', waitForAsync(() => {
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
it('should save current route (empty) and call `login` if not authenticated already', async () => {
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const checkSavedRedirectRouteAndNavigateSpy = spyOn(
|
||||
const checkSavedRedirectRouteAndNavigateSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'checkSavedRedirectRouteAndNavigate'
|
||||
);
|
||||
const saveRedirectRouteSpy = spyOn(
|
||||
const saveRedirectRouteSpy = vi.spyOn(
|
||||
autoLoginService,
|
||||
'saveRedirectRoute'
|
||||
);
|
||||
const loginSpy = spyOn(loginService, 'login');
|
||||
const loginSpy = vi.spyOn(loginService, 'login');
|
||||
|
||||
const guard$ = TestBed.runInInjectionContext(
|
||||
autoLoginPartialRoutesGuardWithConfig('configId1')
|
||||
);
|
||||
|
||||
guard$.subscribe(() => {
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledOnceWith(
|
||||
expect(saveRedirectRouteSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
''
|
||||
);
|
||||
expect(loginSpy).toHaveBeenCalledOnceWith({ configId: 'configId1' });
|
||||
expect(loginSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(checkSavedRedirectRouteAndNavigateSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
Router,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { AuthOptions } from '../auth-options';
|
||||
import type { AuthOptions } from '../auth-options';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { ConfigurationService } from '../config/config.service';
|
||||
import { injectAbstractType } from '../injection';
|
||||
import { LoginService } from '../login/login.service';
|
||||
import {
|
||||
AbstractRouter,
|
||||
type ActivatedRouteSnapshot,
|
||||
type RouterStateSnapshot,
|
||||
} from '../router';
|
||||
import { AutoLoginService } from './auto-login.service';
|
||||
|
||||
@Injectable()
|
||||
@ -22,7 +23,7 @@ export class AutoLoginPartialRoutesGuard {
|
||||
|
||||
private readonly configurationService = inject(ConfigurationService);
|
||||
|
||||
private readonly router = inject(Router);
|
||||
private readonly router = injectAbstractType(AbstractRouter);
|
||||
|
||||
canLoad(): Observable<boolean> {
|
||||
const url =
|
||||
@ -79,14 +80,14 @@ export class AutoLoginPartialRoutesGuard {
|
||||
|
||||
export function autoLoginPartialRoutesGuard(
|
||||
route?: ActivatedRouteSnapshot,
|
||||
state?: RouterStateSnapshot,
|
||||
_state?: RouterStateSnapshot,
|
||||
configId?: string
|
||||
): Observable<boolean> {
|
||||
const configurationService = inject(ConfigurationService);
|
||||
const authStateService = inject(AuthStateService);
|
||||
const loginService = inject(LoginService);
|
||||
const autoLoginService = inject(AutoLoginService);
|
||||
const router = inject(Router);
|
||||
const router = injectAbstractType(AbstractRouter);
|
||||
const authOptions: AuthOptions | undefined = route?.data
|
||||
? { customParams: route.data }
|
||||
: undefined;
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { Router } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { AutoLoginService } from './auto-login.service';
|
||||
|
||||
describe('AutoLoginService ', () => {
|
||||
@ -29,11 +30,11 @@ describe('AutoLoginService ', () => {
|
||||
|
||||
describe('checkSavedRedirectRouteAndNavigate', () => {
|
||||
it('if not route is saved, router and delete are not called', () => {
|
||||
const deleteSpy = spyOn(storagePersistenceService, 'remove');
|
||||
const routerSpy = spyOn(router, 'navigateByUrl');
|
||||
const readSpy = spyOn(storagePersistenceService, 'read').and.returnValue(
|
||||
null
|
||||
);
|
||||
const deleteSpy = vi.spyOn(storagePersistenceService, 'remove');
|
||||
const routerSpy = vi.spyOn(router, 'navigateByUrl');
|
||||
const readSpy = vi
|
||||
.spyOn(storagePersistenceService, 'read')
|
||||
.mockReturnValue(null);
|
||||
|
||||
autoLoginService.checkSavedRedirectRouteAndNavigate({
|
||||
configId: 'configId1',
|
||||
@ -41,27 +42,27 @@ describe('AutoLoginService ', () => {
|
||||
|
||||
expect(deleteSpy).not.toHaveBeenCalled();
|
||||
expect(routerSpy).not.toHaveBeenCalled();
|
||||
expect(readSpy).toHaveBeenCalledOnceWith('redirect', {
|
||||
expect(readSpy).toHaveBeenCalledExactlyOnceWith('redirect', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
|
||||
it('if route is saved, router and delete are called', () => {
|
||||
const deleteSpy = spyOn(storagePersistenceService, 'remove');
|
||||
const routerSpy = spyOn(router, 'navigateByUrl');
|
||||
const readSpy = spyOn(storagePersistenceService, 'read').and.returnValue(
|
||||
'saved-route'
|
||||
);
|
||||
const deleteSpy = vi.spyOn(storagePersistenceService, 'remove');
|
||||
const routerSpy = vi.spyOn(router, 'navigateByUrl');
|
||||
const readSpy = vi
|
||||
.spyOn(storagePersistenceService, 'read')
|
||||
.mockReturnValue('saved-route');
|
||||
|
||||
autoLoginService.checkSavedRedirectRouteAndNavigate({
|
||||
configId: 'configId1',
|
||||
});
|
||||
|
||||
expect(deleteSpy).toHaveBeenCalledOnceWith('redirect', {
|
||||
expect(deleteSpy).toHaveBeenCalledExactlyOnceWith('redirect', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(routerSpy).toHaveBeenCalledOnceWith('saved-route');
|
||||
expect(readSpy).toHaveBeenCalledOnceWith('redirect', {
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('saved-route');
|
||||
expect(readSpy).toHaveBeenCalledExactlyOnceWith('redirect', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
@ -69,16 +70,20 @@ describe('AutoLoginService ', () => {
|
||||
|
||||
describe('saveRedirectRoute', () => {
|
||||
it('calls storageService with correct params', () => {
|
||||
const writeSpy = spyOn(storagePersistenceService, 'write');
|
||||
const writeSpy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
autoLoginService.saveRedirectRoute(
|
||||
{ configId: 'configId1' },
|
||||
'some-route'
|
||||
);
|
||||
|
||||
expect(writeSpy).toHaveBeenCalledOnceWith('redirect', 'some-route', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'redirect',
|
||||
'some-route',
|
||||
{
|
||||
configId: 'configId1',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import { TestBed } from '@/testing';
|
||||
import { Observable, lastValueFrom, of } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
|
||||
import { UrlService } from '../utils/url/url.service';
|
||||
import { CallbackService } from './callback.service';
|
||||
@ -26,9 +27,6 @@ describe('CallbackService ', () => {
|
||||
mockProvider(CodeFlowCallbackService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
callbackService = TestBed.inject(CallbackService);
|
||||
flowHelper = TestBed.inject(FlowHelper);
|
||||
implicitFlowCallbackService = TestBed.inject(ImplicitFlowCallbackService);
|
||||
@ -38,10 +36,13 @@ describe('CallbackService ', () => {
|
||||
|
||||
describe('isCallback', () => {
|
||||
it('calls urlService.isCallbackFromSts with passed url', () => {
|
||||
const urlServiceSpy = spyOn(urlService, 'isCallbackFromSts');
|
||||
const urlServiceSpy = vi.spyOn(urlService, 'isCallbackFromSts');
|
||||
|
||||
callbackService.isCallback('anyUrl');
|
||||
expect(urlServiceSpy).toHaveBeenCalledOnceWith('anyUrl', undefined);
|
||||
expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'anyUrl',
|
||||
undefined
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -52,93 +53,98 @@ describe('CallbackService ', () => {
|
||||
});
|
||||
|
||||
describe('handleCallbackAndFireEvents', () => {
|
||||
it('calls authorizedCallbackWithCode if current flow is code flow', waitForAsync(() => {
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
|
||||
const authorizedCallbackWithCodeSpy = spyOn(
|
||||
codeFlowCallbackService,
|
||||
'authenticatedCallbackWithCode'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
it('calls authorizedCallbackWithCode if current flow is code flow', async () => {
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
|
||||
const authorizedCallbackWithCodeSpy = vi
|
||||
.spyOn(codeFlowCallbackService, 'authenticatedCallbackWithCode')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
callbackService
|
||||
.handleCallbackAndFireEvents('anyUrl', { configId: 'configId1' }, [
|
||||
await lastValueFrom(
|
||||
callbackService.handleCallbackAndFireEvents(
|
||||
'anyUrl',
|
||||
{ configId: 'configId1' },
|
||||
])
|
||||
.subscribe(() => {
|
||||
expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledOnceWith(
|
||||
'anyUrl',
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
);
|
||||
});
|
||||
}));
|
||||
[{ configId: 'configId1' }]
|
||||
)
|
||||
);
|
||||
|
||||
it('calls authorizedImplicitFlowCallback without hash if current flow is implicit flow and callbackurl does not include a hash', waitForAsync(() => {
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
|
||||
spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(true);
|
||||
const authorizedCallbackWithCodeSpy = spyOn(
|
||||
implicitFlowCallbackService,
|
||||
'authenticatedImplicitFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'anyUrl',
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
);
|
||||
});
|
||||
|
||||
callbackService
|
||||
.handleCallbackAndFireEvents('anyUrl', { configId: 'configId1' }, [
|
||||
it('calls authorizedImplicitFlowCallback without hash if current flow is implicit flow and callbackurl does not include a hash', async () => {
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const authorizedCallbackWithCodeSpy = vi
|
||||
.spyOn(implicitFlowCallbackService, 'authenticatedImplicitFlowCallback')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
await lastValueFrom(
|
||||
callbackService.handleCallbackAndFireEvents(
|
||||
'anyUrl',
|
||||
{ configId: 'configId1' },
|
||||
])
|
||||
.subscribe(() => {
|
||||
expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledWith(
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
);
|
||||
});
|
||||
}));
|
||||
[{ configId: 'configId1' }]
|
||||
)
|
||||
);
|
||||
expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledWith(
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
);
|
||||
});
|
||||
|
||||
it('calls authorizedImplicitFlowCallback with hash if current flow is implicit flow and callbackurl does include a hash', waitForAsync(() => {
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
|
||||
spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(true);
|
||||
const authorizedCallbackWithCodeSpy = spyOn(
|
||||
implicitFlowCallbackService,
|
||||
'authenticatedImplicitFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
it('calls authorizedImplicitFlowCallback with hash if current flow is implicit flow and callbackurl does include a hash', async () => {
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const authorizedCallbackWithCodeSpy = vi
|
||||
.spyOn(implicitFlowCallbackService, 'authenticatedImplicitFlowCallback')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
callbackService
|
||||
.handleCallbackAndFireEvents(
|
||||
await lastValueFrom(
|
||||
callbackService.handleCallbackAndFireEvents(
|
||||
'anyUrlWithAHash#some-string',
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
)
|
||||
.subscribe(() => {
|
||||
expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledWith(
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }],
|
||||
'some-string'
|
||||
);
|
||||
});
|
||||
}));
|
||||
);
|
||||
|
||||
it('emits callbackinternal no matter which flow it is', waitForAsync(() => {
|
||||
const callbackSpy = spyOn(
|
||||
expect(authorizedCallbackWithCodeSpy).toHaveBeenCalledWith(
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }],
|
||||
'some-string'
|
||||
);
|
||||
});
|
||||
|
||||
it('emits callbackinternal no matter which flow it is', async () => {
|
||||
const callbackSpy = vi.spyOn(
|
||||
(callbackService as any).stsCallbackInternal$,
|
||||
'next'
|
||||
);
|
||||
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
|
||||
const authenticatedCallbackWithCodeSpy = spyOn(
|
||||
codeFlowCallbackService,
|
||||
'authenticatedCallbackWithCode'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
|
||||
const authenticatedCallbackWithCodeSpy = vi
|
||||
.spyOn(codeFlowCallbackService, 'authenticatedCallbackWithCode')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
callbackService
|
||||
.handleCallbackAndFireEvents('anyUrl', { configId: 'configId1' }, [
|
||||
await lastValueFrom(
|
||||
callbackService.handleCallbackAndFireEvents(
|
||||
'anyUrl',
|
||||
{ configId: 'configId1' },
|
||||
])
|
||||
.subscribe(() => {
|
||||
expect(authenticatedCallbackWithCodeSpy).toHaveBeenCalledOnceWith(
|
||||
'anyUrl',
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
);
|
||||
expect(callbackSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
[{ configId: 'configId1' }]
|
||||
)
|
||||
);
|
||||
|
||||
expect(authenticatedCallbackWithCodeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'anyUrl',
|
||||
{ configId: 'configId1' },
|
||||
[{ configId: 'configId1' }]
|
||||
);
|
||||
expect(callbackSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
|
||||
import { UrlService } from '../utils/url/url.service';
|
||||
import { CodeFlowCallbackService } from './code-flow-callback.service';
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { Router } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TestBed, mockRouterProvider } from '@/testing';
|
||||
import { AbstractRouter } from 'oidc-client-rx';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import { vi } from 'vitest';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { FlowsService } from '../flows/flows.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { CodeFlowCallbackService } from './code-flow-callback.service';
|
||||
import { IntervalService } from './interval.service';
|
||||
|
||||
@ -14,26 +14,24 @@ describe('CodeFlowCallbackService ', () => {
|
||||
let intervalService: IntervalService;
|
||||
let flowsService: FlowsService;
|
||||
let flowsDataService: FlowsDataService;
|
||||
let router: Router;
|
||||
let router: AbstractRouter;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [RouterTestingModule],
|
||||
imports: [],
|
||||
providers: [
|
||||
mockRouterProvider(),
|
||||
CodeFlowCallbackService,
|
||||
mockProvider(FlowsService),
|
||||
mockProvider(FlowsDataService),
|
||||
mockProvider(IntervalService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
codeFlowCallbackService = TestBed.inject(CodeFlowCallbackService);
|
||||
intervalService = TestBed.inject(IntervalService);
|
||||
flowsDataService = TestBed.inject(FlowsDataService);
|
||||
flowsService = TestBed.inject(FlowsService);
|
||||
router = TestBed.inject(Router);
|
||||
router = TestBed.inject(AbstractRouter);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
@ -42,11 +40,10 @@ describe('CodeFlowCallbackService ', () => {
|
||||
|
||||
describe('authenticatedCallbackWithCode', () => {
|
||||
it('calls flowsService.processCodeFlowCallback with correct url', () => {
|
||||
const spy = spyOn(
|
||||
flowsService,
|
||||
'processCodeFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
//spyOn(configurationProvider, 'getOpenIDConfiguration').and.returnValue({ triggerAuthorizationResultEvent: true });
|
||||
const spy = vi
|
||||
.spyOn(flowsService, 'processCodeFlowCallback')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
//spyOn(configurationProvider, 'getOpenIDConfiguration').mockReturnValue({ triggerAuthorizationResultEvent: true });
|
||||
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
@ -58,10 +55,12 @@ describe('CodeFlowCallbackService ', () => {
|
||||
config,
|
||||
[config]
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith('some-url1', config, [config]);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-url1', config, [
|
||||
config,
|
||||
]);
|
||||
});
|
||||
|
||||
it('does only call resetCodeFlowInProgress if triggerAuthorizationResultEvent is true and isRenewProcess is true', waitForAsync(() => {
|
||||
it('does only call resetCodeFlowInProgress if triggerAuthorizationResultEvent is true and isRenewProcess is true', async () => {
|
||||
const callbackContext = {
|
||||
code: '',
|
||||
refreshToken: '',
|
||||
@ -73,12 +72,14 @@ describe('CodeFlowCallbackService ', () => {
|
||||
validationResult: null,
|
||||
existingIdToken: '',
|
||||
};
|
||||
const spy = spyOn(
|
||||
flowsService,
|
||||
'processCodeFlowCallback'
|
||||
).and.returnValue(of(callbackContext));
|
||||
const flowsDataSpy = spyOn(flowsDataService, 'resetCodeFlowInProgress');
|
||||
const routerSpy = spyOn(router, 'navigateByUrl');
|
||||
const spy = vi
|
||||
.spyOn(flowsService, 'processCodeFlowCallback')
|
||||
.mockReturnValue(of(callbackContext));
|
||||
const flowsDataSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetCodeFlowInProgress'
|
||||
);
|
||||
const routerSpy = vi.spyOn(router, 'navigateByUrl');
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
triggerAuthorizationResultEvent: true,
|
||||
@ -87,13 +88,15 @@ describe('CodeFlowCallbackService ', () => {
|
||||
codeFlowCallbackService
|
||||
.authenticatedCallbackWithCode('some-url2', config, [config])
|
||||
.subscribe(() => {
|
||||
expect(spy).toHaveBeenCalledOnceWith('some-url2', config, [config]);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-url2', config, [
|
||||
config,
|
||||
]);
|
||||
expect(routerSpy).not.toHaveBeenCalled();
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls router and resetCodeFlowInProgress if triggerAuthorizationResultEvent is false and isRenewProcess is false', waitForAsync(() => {
|
||||
it('calls router and resetCodeFlowInProgress if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => {
|
||||
const callbackContext = {
|
||||
code: '',
|
||||
refreshToken: '',
|
||||
@ -105,12 +108,14 @@ describe('CodeFlowCallbackService ', () => {
|
||||
validationResult: null,
|
||||
existingIdToken: '',
|
||||
};
|
||||
const spy = spyOn(
|
||||
flowsService,
|
||||
'processCodeFlowCallback'
|
||||
).and.returnValue(of(callbackContext));
|
||||
const flowsDataSpy = spyOn(flowsDataService, 'resetCodeFlowInProgress');
|
||||
const routerSpy = spyOn(router, 'navigateByUrl');
|
||||
const spy = vi
|
||||
.spyOn(flowsService, 'processCodeFlowCallback')
|
||||
.mockReturnValue(of(callbackContext));
|
||||
const flowsDataSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetCodeFlowInProgress'
|
||||
);
|
||||
const routerSpy = vi.spyOn(router, 'navigateByUrl');
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
triggerAuthorizationResultEvent: false,
|
||||
@ -120,25 +125,27 @@ describe('CodeFlowCallbackService ', () => {
|
||||
codeFlowCallbackService
|
||||
.authenticatedCallbackWithCode('some-url3', config, [config])
|
||||
.subscribe(() => {
|
||||
expect(spy).toHaveBeenCalledOnceWith('some-url3', config, [config]);
|
||||
expect(routerSpy).toHaveBeenCalledOnceWith('postLoginRoute');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-url3', config, [
|
||||
config,
|
||||
]);
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('resetSilentRenewRunning, resetCodeFlowInProgress and stopPeriodicallTokenCheck in case of error', waitForAsync(() => {
|
||||
spyOn(flowsService, 'processCodeFlowCallback').and.returnValue(
|
||||
it('resetSilentRenewRunning, resetCodeFlowInProgress and stopPeriodicallTokenCheck in case of error', async () => {
|
||||
vi.spyOn(flowsService, 'processCodeFlowCallback').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
const resetSilentRenewRunningSpy = spyOn(
|
||||
const resetSilentRenewRunningSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
const resetCodeFlowInProgressSpy = spyOn(
|
||||
const resetCodeFlowInProgressSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetCodeFlowInProgress'
|
||||
);
|
||||
const stopPeriodicallTokenCheckSpy = spyOn(
|
||||
const stopPeriodicallTokenCheckSpy = vi.spyOn(
|
||||
intervalService,
|
||||
'stopPeriodicTokenCheck'
|
||||
);
|
||||
@ -159,23 +166,23 @@ describe('CodeFlowCallbackService ', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`navigates to unauthorizedRoute in case of error and in case of error and
|
||||
triggerAuthorizationResultEvent is false`, waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(flowsService, 'processCodeFlowCallback').and.returnValue(
|
||||
triggerAuthorizationResultEvent is false`, async () => {
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(flowsService, 'processCodeFlowCallback').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
const resetSilentRenewRunningSpy = spyOn(
|
||||
const resetSilentRenewRunningSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
const stopPeriodicallTokenCheckSpy = spyOn(
|
||||
const stopPeriodicallTokenCheckSpy = vi.spyOn(
|
||||
intervalService,
|
||||
'stopPeriodicTokenCheck'
|
||||
);
|
||||
const routerSpy = spyOn(router, 'navigateByUrl');
|
||||
const routerSpy = vi.spyOn(router, 'navigateByUrl');
|
||||
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
@ -190,9 +197,11 @@ describe('CodeFlowCallbackService ', () => {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
expect(routerSpy).toHaveBeenCalledOnceWith('unauthorizedRoute');
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'unauthorizedRoute'
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Router } from '@angular/router';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, tap } from 'rxjs/operators';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { FlowsService } from '../flows/flows.service';
|
||||
import { IntervalService } from './interval.service';
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { Router } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TestBed, mockRouterProvider } from '@/testing';
|
||||
import { AbstractRouter } from 'oidc-client-rx';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import { vi } from 'vitest';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { FlowsService } from '../flows/flows.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { ImplicitFlowCallbackService } from './implicit-flow-callback.service';
|
||||
import { IntervalService } from './interval.service';
|
||||
|
||||
@ -14,25 +14,23 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
let intervalService: IntervalService;
|
||||
let flowsService: FlowsService;
|
||||
let flowsDataService: FlowsDataService;
|
||||
let router: Router;
|
||||
let router: AbstractRouter;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [RouterTestingModule],
|
||||
imports: [],
|
||||
providers: [
|
||||
mockRouterProvider(),
|
||||
mockProvider(FlowsService),
|
||||
mockProvider(FlowsDataService),
|
||||
mockProvider(IntervalService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
implicitFlowCallbackService = TestBed.inject(ImplicitFlowCallbackService);
|
||||
intervalService = TestBed.inject(IntervalService);
|
||||
flowsDataService = TestBed.inject(FlowsDataService);
|
||||
flowsService = TestBed.inject(FlowsService);
|
||||
router = TestBed.inject(Router);
|
||||
router = TestBed.inject(AbstractRouter);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
@ -41,10 +39,9 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
|
||||
describe('authorizedImplicitFlowCallback', () => {
|
||||
it('calls flowsService.processImplicitFlowCallback with hash if given', () => {
|
||||
const spy = spyOn(
|
||||
flowsService,
|
||||
'processImplicitFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const spy = vi
|
||||
.spyOn(flowsService, 'processImplicitFlowCallback')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
triggerAuthorizationResultEvent: true,
|
||||
@ -56,10 +53,14 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
'some-hash'
|
||||
);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith(config, [config], 'some-hash');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
);
|
||||
});
|
||||
|
||||
it('does nothing if triggerAuthorizationResultEvent is true and isRenewProcess is true', waitForAsync(() => {
|
||||
it('does nothing if triggerAuthorizationResultEvent is true and isRenewProcess is true', async () => {
|
||||
const callbackContext = {
|
||||
code: '',
|
||||
refreshToken: '',
|
||||
@ -71,11 +72,10 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
validationResult: null,
|
||||
existingIdToken: '',
|
||||
};
|
||||
const spy = spyOn(
|
||||
flowsService,
|
||||
'processImplicitFlowCallback'
|
||||
).and.returnValue(of(callbackContext));
|
||||
const routerSpy = spyOn(router, 'navigateByUrl');
|
||||
const spy = vi
|
||||
.spyOn(flowsService, 'processImplicitFlowCallback')
|
||||
.mockReturnValue(of(callbackContext));
|
||||
const routerSpy = vi.spyOn(router, 'navigateByUrl');
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
triggerAuthorizationResultEvent: true,
|
||||
@ -84,12 +84,16 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
implicitFlowCallbackService
|
||||
.authenticatedImplicitFlowCallback(config, [config], 'some-hash')
|
||||
.subscribe(() => {
|
||||
expect(spy).toHaveBeenCalledOnceWith(config, [config], 'some-hash');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
);
|
||||
expect(routerSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls router if triggerAuthorizationResultEvent is false and isRenewProcess is false', waitForAsync(() => {
|
||||
it('calls router if triggerAuthorizationResultEvent is false and isRenewProcess is false', async () => {
|
||||
const callbackContext = {
|
||||
code: '',
|
||||
refreshToken: '',
|
||||
@ -101,11 +105,10 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
validationResult: null,
|
||||
existingIdToken: '',
|
||||
};
|
||||
const spy = spyOn(
|
||||
flowsService,
|
||||
'processImplicitFlowCallback'
|
||||
).and.returnValue(of(callbackContext));
|
||||
const routerSpy = spyOn(router, 'navigateByUrl');
|
||||
const spy = vi
|
||||
.spyOn(flowsService, 'processImplicitFlowCallback')
|
||||
.mockReturnValue(of(callbackContext));
|
||||
const routerSpy = vi.spyOn(router, 'navigateByUrl');
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
triggerAuthorizationResultEvent: false,
|
||||
@ -115,20 +118,24 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
implicitFlowCallbackService
|
||||
.authenticatedImplicitFlowCallback(config, [config], 'some-hash')
|
||||
.subscribe(() => {
|
||||
expect(spy).toHaveBeenCalledOnceWith(config, [config], 'some-hash');
|
||||
expect(routerSpy).toHaveBeenCalledOnceWith('postLoginRoute');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
[config],
|
||||
'some-hash'
|
||||
);
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith('postLoginRoute');
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('resetSilentRenewRunning and stopPeriodicallyTokenCheck in case of error', waitForAsync(() => {
|
||||
spyOn(flowsService, 'processImplicitFlowCallback').and.returnValue(
|
||||
it('resetSilentRenewRunning and stopPeriodicallyTokenCheck in case of error', async () => {
|
||||
vi.spyOn(flowsService, 'processImplicitFlowCallback').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
const resetSilentRenewRunningSpy = spyOn(
|
||||
const resetSilentRenewRunningSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
const stopPeriodicallyTokenCheckSpy = spyOn(
|
||||
const stopPeriodicallyTokenCheckSpy = vi.spyOn(
|
||||
intervalService,
|
||||
'stopPeriodicTokenCheck'
|
||||
);
|
||||
@ -147,23 +154,23 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`navigates to unauthorizedRoute in case of error and in case of error and
|
||||
triggerAuthorizationResultEvent is false`, waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(flowsService, 'processImplicitFlowCallback').and.returnValue(
|
||||
triggerAuthorizationResultEvent is false`, async () => {
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(flowsService, 'processImplicitFlowCallback').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
const resetSilentRenewRunningSpy = spyOn(
|
||||
const resetSilentRenewRunningSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
const stopPeriodicallTokenCheckSpy = spyOn(
|
||||
const stopPeriodicallTokenCheckSpy = vi.spyOn(
|
||||
intervalService,
|
||||
'stopPeriodicTokenCheck'
|
||||
);
|
||||
const routerSpy = spyOn(router, 'navigateByUrl');
|
||||
const routerSpy = vi.spyOn(router, 'navigateByUrl');
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
triggerAuthorizationResultEvent: false,
|
||||
@ -177,9 +184,11 @@ describe('ImplicitFlowCallbackService ', () => {
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
expect(stopPeriodicallTokenCheckSpy).toHaveBeenCalled();
|
||||
expect(err).toBeTruthy();
|
||||
expect(routerSpy).toHaveBeenCalledOnceWith('unauthorizedRoute');
|
||||
expect(routerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'unauthorizedRoute'
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Router } from '@angular/router';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, tap } from 'rxjs/operators';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { FlowsService } from '../flows/flows.service';
|
||||
import { IntervalService } from './interval.service';
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { TestBed, fakeAsync, tick } from '@/testing';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { IntervalService } from './interval.service';
|
||||
|
||||
describe('IntervalService', () => {
|
||||
@ -31,7 +32,7 @@ describe('IntervalService', () => {
|
||||
describe('stopPeriodicTokenCheck', () => {
|
||||
it('calls unsubscribe and sets to null', () => {
|
||||
intervalService.runTokenValidationRunning = new Subscription();
|
||||
const spy = spyOn(
|
||||
const spy = vi.spyOn(
|
||||
intervalService.runTokenValidationRunning,
|
||||
'unsubscribe'
|
||||
);
|
||||
@ -44,7 +45,7 @@ describe('IntervalService', () => {
|
||||
|
||||
it('does nothing if `runTokenValidationRunning` is null', () => {
|
||||
intervalService.runTokenValidationRunning = new Subscription();
|
||||
const spy = spyOn(
|
||||
const spy = vi.spyOn(
|
||||
intervalService.runTokenValidationRunning,
|
||||
'unsubscribe'
|
||||
);
|
||||
@ -57,7 +58,7 @@ describe('IntervalService', () => {
|
||||
});
|
||||
|
||||
describe('startPeriodicTokenCheck', () => {
|
||||
it('starts check after correct milliseconds', fakeAsync(() => {
|
||||
it('starts check after correct milliseconds', async () => {
|
||||
const periodicCheck = intervalService.startPeriodicTokenCheck(0.5);
|
||||
const spy = jasmine.createSpy();
|
||||
const sub = periodicCheck.subscribe(() => {
|
||||
@ -71,6 +72,6 @@ describe('IntervalService', () => {
|
||||
expect(spy).toHaveBeenCalledTimes(2);
|
||||
|
||||
sub.unsubscribe();
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { Injectable, NgZone, inject } from 'injection-js';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, type Subscription, interval } from 'rxjs';
|
||||
import { DOCUMENT } from '../dom';
|
||||
|
||||
@Injectable()
|
||||
export class IntervalService {
|
||||
private readonly zone = inject(NgZone);
|
||||
|
||||
private readonly document = inject(DOCUMENT);
|
||||
|
||||
runTokenValidationRunning: Subscription | null = null;
|
||||
@ -24,19 +22,6 @@ export class IntervalService {
|
||||
startPeriodicTokenCheck(repeatAfterSeconds: number): Observable<unknown> {
|
||||
const millisecondsDelayBetweenTokenCheck = repeatAfterSeconds * 1000;
|
||||
|
||||
return new Observable((subscriber) => {
|
||||
let intervalId: number | undefined;
|
||||
|
||||
this.zone.runOutsideAngular(() => {
|
||||
intervalId = this.document?.defaultView?.setInterval(
|
||||
() => this.zone.run(() => subscriber.next()),
|
||||
millisecondsDelayBetweenTokenCheck
|
||||
);
|
||||
});
|
||||
|
||||
return (): void => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
});
|
||||
return interval(millisecondsDelayBetweenTokenCheck);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { TestBed } from '@/testing';
|
||||
import { lastValueFrom, of, throwError } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { ConfigurationService } from '../config/config.service';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
|
||||
import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service';
|
||||
@ -12,6 +12,7 @@ import { LoggerService } from '../logging/logger.service';
|
||||
import { EventTypes } from '../public-events/event-types';
|
||||
import { PublicEventsService } from '../public-events/public-events.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { UserService } from '../user-data/user.service';
|
||||
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
|
||||
import { IntervalService } from './interval.service';
|
||||
@ -49,9 +50,6 @@ describe('PeriodicallyTokenCheckService', () => {
|
||||
mockProvider(ConfigurationService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
periodicallyTokenCheckService = TestBed.inject(
|
||||
PeriodicallyTokenCheckService
|
||||
);
|
||||
@ -68,11 +66,14 @@ describe('PeriodicallyTokenCheckService', () => {
|
||||
publicEventsService = TestBed.inject(PublicEventsService);
|
||||
configurationService = TestBed.inject(ConfigurationService);
|
||||
|
||||
spyOn(intervalService, 'startPeriodicTokenCheck').and.returnValue(of(null));
|
||||
vi.spyOn(intervalService, 'startPeriodicTokenCheck').mockReturnValue(
|
||||
of(null)
|
||||
);
|
||||
});
|
||||
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: <explanation>
|
||||
afterEach(() => {
|
||||
if (!!intervalService.runTokenValidationRunning?.unsubscribe) {
|
||||
if (intervalService.runTokenValidationRunning?.unsubscribe) {
|
||||
intervalService.runTokenValidationRunning.unsubscribe();
|
||||
intervalService.runTokenValidationRunning = null;
|
||||
}
|
||||
@ -83,164 +84,172 @@ describe('PeriodicallyTokenCheckService', () => {
|
||||
});
|
||||
|
||||
describe('startTokenValidationPeriodically', () => {
|
||||
it('returns if no config has silentrenew enabled', waitForAsync(() => {
|
||||
it('returns if no config has silentrenew enabled', async () => {
|
||||
const configs = [
|
||||
{ silentRenew: false, configId: 'configId1' },
|
||||
{ silentRenew: false, configId: 'configId2' },
|
||||
];
|
||||
|
||||
const result =
|
||||
const result = await lastValueFrom(
|
||||
periodicallyTokenCheckService.startTokenValidationPeriodically(
|
||||
configs,
|
||||
configs[0]
|
||||
);
|
||||
configs[0]!
|
||||
)
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns if runTokenValidationRunning', waitForAsync(() => {
|
||||
it('returns if runTokenValidationRunning', async () => {
|
||||
const configs = [{ silentRenew: true, configId: 'configId1' }];
|
||||
|
||||
spyOn(intervalService, 'isTokenValidationRunning').and.returnValue(true);
|
||||
vi.spyOn(intervalService, 'isTokenValidationRunning').mockReturnValue(
|
||||
true
|
||||
);
|
||||
|
||||
const result =
|
||||
const result = await lastValueFrom(
|
||||
periodicallyTokenCheckService.startTokenValidationPeriodically(
|
||||
configs,
|
||||
configs[0]
|
||||
);
|
||||
configs[0]!
|
||||
)
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
}));
|
||||
});
|
||||
|
||||
it('interval calls resetSilentRenewRunning when current flow is CodeFlowWithRefreshTokens', fakeAsync(() => {
|
||||
it('interval calls resetSilentRenewRunning when current flow is CodeFlowWithRefreshTokens', async () => {
|
||||
const configs = [
|
||||
{ silentRenew: true, configId: 'configId1', tokenRefreshInSeconds: 1 },
|
||||
];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
periodicallyTokenCheckService as any,
|
||||
'shouldStartPeriodicallyCheckForConfig'
|
||||
).and.returnValue(true);
|
||||
const isCurrentFlowCodeFlowWithRefreshTokensSpy = spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
const resetSilentRenewRunningSpy = spyOn(
|
||||
).mockReturnValue(true);
|
||||
const isCurrentFlowCodeFlowWithRefreshTokensSpy = vi
|
||||
.spyOn(flowHelper, 'isCurrentFlowCodeFlowWithRefreshTokens')
|
||||
.mockReturnValue(true);
|
||||
const resetSilentRenewRunningSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
|
||||
of(configs[0])
|
||||
).mockReturnValue(of({} as CallbackContext));
|
||||
vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
|
||||
of(configs[0]!)
|
||||
);
|
||||
|
||||
periodicallyTokenCheckService.startTokenValidationPeriodically(
|
||||
configs,
|
||||
configs[0]
|
||||
configs[0]!
|
||||
);
|
||||
|
||||
tick(1000);
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
|
||||
intervalService.runTokenValidationRunning?.unsubscribe();
|
||||
intervalService.runTokenValidationRunning = null;
|
||||
expect(isCurrentFlowCodeFlowWithRefreshTokensSpy).toHaveBeenCalled();
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('interval calls resetSilentRenewRunning in case of error when current flow is CodeFlowWithRefreshTokens', fakeAsync(() => {
|
||||
it('interval calls resetSilentRenewRunning in case of error when current flow is CodeFlowWithRefreshTokens', async () => {
|
||||
const configs = [
|
||||
{ silentRenew: true, configId: 'configId1', tokenRefreshInSeconds: 1 },
|
||||
];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
periodicallyTokenCheckService as any,
|
||||
'shouldStartPeriodicallyCheckForConfig'
|
||||
).and.returnValue(true);
|
||||
const resetSilentRenewRunning = spyOn(
|
||||
).mockReturnValue(true);
|
||||
const resetSilentRenewRunning = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
).and.returnValue(throwError(() => new Error('error')));
|
||||
spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
|
||||
of(configs[0])
|
||||
).mockReturnValue(throwError(() => new Error('error')));
|
||||
vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
|
||||
of(configs[0]!)
|
||||
);
|
||||
|
||||
periodicallyTokenCheckService.startTokenValidationPeriodically(
|
||||
configs,
|
||||
configs[0]
|
||||
configs[0]!
|
||||
);
|
||||
|
||||
tick(1000);
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
|
||||
expect(
|
||||
periodicallyTokenCheckService.startTokenValidationPeriodically
|
||||
).toThrowError();
|
||||
expect(resetSilentRenewRunning).toHaveBeenCalledOnceWith(configs[0]);
|
||||
}));
|
||||
expect(resetSilentRenewRunning).toHaveBeenCalledExactlyOnceWith(
|
||||
configs[0]
|
||||
);
|
||||
});
|
||||
|
||||
it('interval throws silent renew failed event with data in case of an error', fakeAsync(() => {
|
||||
it('interval throws silent renew failed event with data in case of an error', async () => {
|
||||
const configs = [
|
||||
{ silentRenew: true, configId: 'configId1', tokenRefreshInSeconds: 1 },
|
||||
];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
periodicallyTokenCheckService as any,
|
||||
'shouldStartPeriodicallyCheckForConfig'
|
||||
).and.returnValue(true);
|
||||
spyOn(flowsDataService, 'resetSilentRenewRunning');
|
||||
const publicEventsServiceSpy = spyOn(publicEventsService, 'fireEvent');
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(flowsDataService, 'resetSilentRenewRunning');
|
||||
const publicEventsServiceSpy = vi.spyOn(publicEventsService, 'fireEvent');
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
).and.returnValue(throwError(() => new Error('error')));
|
||||
spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
|
||||
of(configs[0])
|
||||
).mockReturnValue(throwError(() => new Error('error')));
|
||||
vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
|
||||
of(configs[0]!)
|
||||
);
|
||||
|
||||
periodicallyTokenCheckService.startTokenValidationPeriodically(
|
||||
configs,
|
||||
configs[0]
|
||||
configs[0]!
|
||||
);
|
||||
|
||||
tick(1000);
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
|
||||
expect(
|
||||
periodicallyTokenCheckService.startTokenValidationPeriodically
|
||||
).toThrowError();
|
||||
expect(publicEventsServiceSpy.calls.allArgs()).toEqual([
|
||||
expect(publicEventsServiceSpy).toBeCalledWith([
|
||||
[EventTypes.SilentRenewStarted],
|
||||
[EventTypes.SilentRenewFailed, new Error('error')],
|
||||
]);
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls resetAuthorizationData and returns if no silent renew is configured', fakeAsync(() => {
|
||||
it('calls resetAuthorizationData and returns if no silent renew is configured', async () => {
|
||||
const configs = [
|
||||
{ silentRenew: true, configId: 'configId1', tokenRefreshInSeconds: 1 },
|
||||
];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
periodicallyTokenCheckService as any,
|
||||
'shouldStartPeriodicallyCheckForConfig'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
|
||||
const configSpy = spyOn(configurationService, 'getOpenIDConfiguration');
|
||||
const configSpy = vi.spyOn(
|
||||
configurationService,
|
||||
'getOpenIDConfiguration'
|
||||
);
|
||||
const configWithoutSilentRenew = {
|
||||
silentRenew: false,
|
||||
configId: 'configId1',
|
||||
@ -248,68 +257,70 @@ describe('PeriodicallyTokenCheckService', () => {
|
||||
};
|
||||
const configWithoutSilentRenew$ = of(configWithoutSilentRenew);
|
||||
|
||||
configSpy.and.returnValue(configWithoutSilentRenew$);
|
||||
configSpy.mockReturnValue(configWithoutSilentRenew$);
|
||||
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
|
||||
periodicallyTokenCheckService.startTokenValidationPeriodically(
|
||||
configs,
|
||||
configs[0]
|
||||
configs[0]!
|
||||
);
|
||||
tick(1000);
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
intervalService.runTokenValidationRunning?.unsubscribe();
|
||||
intervalService.runTokenValidationRunning = null;
|
||||
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledOnceWith(
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
configWithoutSilentRenew,
|
||||
configs
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls refreshSessionWithRefreshTokens if current flow is Code flow with refresh tokens', fakeAsync(() => {
|
||||
spyOn(
|
||||
it('calls refreshSessionWithRefreshTokens if current flow is Code flow with refresh tokens', async () => {
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
periodicallyTokenCheckService as any,
|
||||
'shouldStartPeriodicallyCheckForConfig'
|
||||
).and.returnValue(true);
|
||||
spyOn(storagePersistenceService, 'read').and.returnValue({});
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(storagePersistenceService, 'read').mockReturnValue({});
|
||||
const configs = [
|
||||
{ configId: 'configId1', silentRenew: true, tokenRefreshInSeconds: 1 },
|
||||
];
|
||||
|
||||
spyOn(configurationService, 'getOpenIDConfiguration').and.returnValue(
|
||||
vi.spyOn(configurationService, 'getOpenIDConfiguration').mockReturnValue(
|
||||
of(configs[0] as OpenIdConfiguration)
|
||||
);
|
||||
const refreshSessionWithRefreshTokensSpy = spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const refreshSessionWithRefreshTokensSpy = vi
|
||||
.spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
)
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
periodicallyTokenCheckService.startTokenValidationPeriodically(
|
||||
configs,
|
||||
configs[0]
|
||||
configs[0]!
|
||||
);
|
||||
|
||||
tick(1000);
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
|
||||
intervalService.runTokenValidationRunning?.unsubscribe();
|
||||
intervalService.runTokenValidationRunning = null;
|
||||
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('shouldStartPeriodicallyCheckForConfig', () => {
|
||||
it('returns false when there is no IdToken', () => {
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('');
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(userService, 'getUserDataFromStore').and.returnValue(
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('');
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
|
||||
'some-userdata'
|
||||
);
|
||||
|
||||
@ -317,13 +328,13 @@ describe('PeriodicallyTokenCheckService', () => {
|
||||
periodicallyTokenCheckService as any
|
||||
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false when silent renew is running', () => {
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
|
||||
spyOn(userService, 'getUserDataFromStore').and.returnValue(
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
|
||||
vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
|
||||
'some-userdata'
|
||||
);
|
||||
|
||||
@ -331,14 +342,14 @@ describe('PeriodicallyTokenCheckService', () => {
|
||||
periodicallyTokenCheckService as any
|
||||
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false when code flow is in progress', () => {
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(flowsDataService, 'isCodeFlowInProgress').and.returnValue(true);
|
||||
spyOn(userService, 'getUserDataFromStore').and.returnValue(
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(flowsDataService, 'isCodeFlowInProgress').mockReturnValue(true);
|
||||
vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
|
||||
'some-userdata'
|
||||
);
|
||||
|
||||
@ -346,87 +357,87 @@ describe('PeriodicallyTokenCheckService', () => {
|
||||
periodicallyTokenCheckService as any
|
||||
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false when there is no userdata from the store', () => {
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
|
||||
spyOn(userService, 'getUserDataFromStore').and.returnValue(null);
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
|
||||
vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(null);
|
||||
|
||||
const result = (
|
||||
periodicallyTokenCheckService as any
|
||||
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns true when there is userDataFromStore, silentrenew is not running and there is an idtoken', () => {
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(userService, 'getUserDataFromStore').and.returnValue(
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
|
||||
'some-userdata'
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authStateService,
|
||||
'hasIdTokenExpiredAndRenewCheckIsEnabled'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authStateService,
|
||||
'hasAccessTokenExpiredIfExpiryExists'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
|
||||
const result = (
|
||||
periodicallyTokenCheckService as any
|
||||
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBeTrue();
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns false if tokens are not expired', () => {
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(userService, 'getUserDataFromStore').and.returnValue(
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
|
||||
'some-userdata'
|
||||
);
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authStateService,
|
||||
'hasIdTokenExpiredAndRenewCheckIsEnabled'
|
||||
).and.returnValue(false);
|
||||
spyOn(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
authStateService,
|
||||
'hasAccessTokenExpiredIfExpiryExists'
|
||||
).and.returnValue(false);
|
||||
).mockReturnValue(false);
|
||||
|
||||
const result = (
|
||||
periodicallyTokenCheckService as any
|
||||
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns true if tokens are expired', () => {
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('idToken');
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(userService, 'getUserDataFromStore').and.returnValue(
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('idToken');
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(userService, 'getUserDataFromStore').mockReturnValue(
|
||||
'some-userdata'
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authStateService,
|
||||
'hasIdTokenExpiredAndRenewCheckIsEnabled'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authStateService,
|
||||
'hasAccessTokenExpiredIfExpiryExists'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
|
||||
const result = (
|
||||
periodicallyTokenCheckService as any
|
||||
).shouldStartPeriodicallyCheckForConfig({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBeTrue();
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { forkJoin, Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, switchMap } from 'rxjs/operators';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, forkJoin, of, throwError } from 'rxjs';
|
||||
import { catchError, map, shareReplay, switchMap } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { ConfigurationService } from '../config/config.service';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
|
||||
import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service';
|
||||
@ -52,7 +52,7 @@ export class PeriodicallyTokenCheckService {
|
||||
startTokenValidationPeriodically(
|
||||
allConfigs: OpenIdConfiguration[],
|
||||
currentConfig: OpenIdConfiguration
|
||||
): void {
|
||||
): Observable<void> {
|
||||
const configsWithSilentRenewEnabled =
|
||||
this.getConfigsWithSilentRenewEnabled(allConfigs);
|
||||
|
||||
@ -75,46 +75,51 @@ export class PeriodicallyTokenCheckService {
|
||||
[id: string]: Observable<boolean | CallbackContext | null>;
|
||||
} = {};
|
||||
|
||||
configsWithSilentRenewEnabled.forEach((config) => {
|
||||
for (const config of configsWithSilentRenewEnabled) {
|
||||
const identifier = config.configId as string;
|
||||
const refreshEvent = this.getRefreshEvent(config, allConfigs);
|
||||
|
||||
objectWithConfigIdsAndRefreshEvent[identifier] = refreshEvent;
|
||||
});
|
||||
}
|
||||
|
||||
return forkJoin(objectWithConfigIdsAndRefreshEvent);
|
||||
})
|
||||
);
|
||||
|
||||
this.intervalService.runTokenValidationRunning = periodicallyCheck$
|
||||
.pipe(catchError((error) => throwError(() => new Error(error))))
|
||||
.subscribe({
|
||||
next: (objectWithConfigIds) => {
|
||||
for (const [configId, _] of Object.entries(objectWithConfigIds)) {
|
||||
this.configurationService
|
||||
.getOpenIDConfiguration(configId)
|
||||
.subscribe((config) => {
|
||||
this.loggerService.logDebug(
|
||||
config,
|
||||
'silent renew, periodic check finished!'
|
||||
);
|
||||
const o$ = periodicallyCheck$.pipe(
|
||||
catchError((error) => throwError(() => new Error(error))),
|
||||
map((objectWithConfigIds) => {
|
||||
for (const [configId, _] of Object.entries(objectWithConfigIds)) {
|
||||
this.configurationService
|
||||
.getOpenIDConfiguration(configId)
|
||||
.subscribe((config) => {
|
||||
this.loggerService.logDebug(
|
||||
config,
|
||||
'silent renew, periodic check finished!'
|
||||
);
|
||||
|
||||
if (
|
||||
this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens(config)
|
||||
) {
|
||||
this.flowsDataService.resetSilentRenewRunning(config);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
this.loggerService.logError(
|
||||
currentConfig,
|
||||
'silent renew failed!',
|
||||
error
|
||||
);
|
||||
},
|
||||
});
|
||||
if (
|
||||
this.flowHelper.isCurrentFlowCodeFlowWithRefreshTokens(config)
|
||||
) {
|
||||
this.flowsDataService.resetSilentRenewRunning(config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}),
|
||||
catchError((error) => {
|
||||
this.loggerService.logError(
|
||||
currentConfig,
|
||||
'silent renew failed!',
|
||||
error
|
||||
);
|
||||
return throwError(() => error);
|
||||
}),
|
||||
shareReplay(1)
|
||||
);
|
||||
|
||||
this.intervalService.runTokenValidationRunning = o$.subscribe();
|
||||
|
||||
return o$;
|
||||
}
|
||||
|
||||
private getRefreshEvent(
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import { vi } from 'vitest';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsService } from '../flows/flows.service';
|
||||
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { IntervalService } from './interval.service';
|
||||
import { RefreshSessionRefreshTokenService } from './refresh-session-refresh-token.service';
|
||||
|
||||
@ -25,9 +26,6 @@ describe('RefreshSessionRefreshTokenService', () => {
|
||||
mockProvider(IntervalService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
flowsService = TestBed.inject(FlowsService);
|
||||
refreshSessionRefreshTokenService = TestBed.inject(
|
||||
RefreshSessionRefreshTokenService
|
||||
@ -41,10 +39,10 @@ describe('RefreshSessionRefreshTokenService', () => {
|
||||
});
|
||||
|
||||
describe('refreshSessionWithRefreshTokens', () => {
|
||||
it('calls flowsService.processRefreshToken()', waitForAsync(() => {
|
||||
const spy = spyOn(flowsService, 'processRefreshToken').and.returnValue(
|
||||
of({} as CallbackContext)
|
||||
);
|
||||
it('calls flowsService.processRefreshToken()', async () => {
|
||||
const spy = vi
|
||||
.spyOn(flowsService, 'processRefreshToken')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
refreshSessionRefreshTokenService
|
||||
.refreshSessionWithRefreshTokens({ configId: 'configId1' }, [
|
||||
@ -53,13 +51,13 @@ describe('RefreshSessionRefreshTokenService', () => {
|
||||
.subscribe(() => {
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('resetAuthorizationData in case of error', waitForAsync(() => {
|
||||
spyOn(flowsService, 'processRefreshToken').and.returnValue(
|
||||
it('resetAuthorizationData in case of error', async () => {
|
||||
vi.spyOn(flowsService, 'processRefreshToken').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
const resetSilentRenewRunningSpy = spyOn(
|
||||
const resetSilentRenewRunningSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
@ -74,13 +72,13 @@ describe('RefreshSessionRefreshTokenService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('finalize with stopPeriodicTokenCheck in case of error', fakeAsync(() => {
|
||||
spyOn(flowsService, 'processRefreshToken').and.returnValue(
|
||||
it('finalize with stopPeriodicTokenCheck in case of error', async () => {
|
||||
vi.spyOn(flowsService, 'processRefreshToken').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
const stopPeriodicallyTokenCheckSpy = spyOn(
|
||||
const stopPeriodicallyTokenCheckSpy = vi.spyOn(
|
||||
intervalService,
|
||||
'stopPeriodicTokenCheck'
|
||||
);
|
||||
@ -94,8 +92,8 @@ describe('RefreshSessionRefreshTokenService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
tick();
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
expect(stopPeriodicallyTokenCheckSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs/operators';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsService } from '../flows/flows.service';
|
||||
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
|
@ -1,17 +1,18 @@
|
||||
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, fakeAsync, tick } from '@/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { delay } from 'rxjs/operators';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { AuthWellKnownService } from '../config/auth-well-known/auth-well-known.service';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service';
|
||||
import { SilentRenewService } from '../iframe/silent-renew.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { LoginResponse } from '../login/login-response';
|
||||
import type { LoginResponse } from '../login/login-response';
|
||||
import { PublicEventsService } from '../public-events/public-events.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { UserService } from '../user-data/user.service';
|
||||
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
|
||||
import { RefreshSessionRefreshTokenService } from './refresh-session-refresh-token.service';
|
||||
@ -70,19 +71,19 @@ describe('RefreshSessionService ', () => {
|
||||
});
|
||||
|
||||
describe('userForceRefreshSession', () => {
|
||||
it('should persist params refresh when extra custom params given and useRefreshToken is true', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('should persist params refresh when extra custom params given and useRefreshToken is true', async () => {
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const writeSpy = spyOn(storagePersistenceService, 'write');
|
||||
const writeSpy = vi.spyOn(storagePersistenceService, 'write');
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -94,26 +95,26 @@ describe('RefreshSessionService ', () => {
|
||||
const extraCustomParams = { extra: 'custom' };
|
||||
|
||||
refreshSessionService
|
||||
.userForceRefreshSession(allConfigs[0], allConfigs, extraCustomParams)
|
||||
.userForceRefreshSession(allConfigs[0]!, allConfigs, extraCustomParams)
|
||||
.subscribe(() => {
|
||||
expect(writeSpy).toHaveBeenCalledOnceWith(
|
||||
expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageCustomParamsRefresh',
|
||||
extraCustomParams,
|
||||
allConfigs[0]
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should persist storageCustomParamsAuthRequest when extra custom params given and useRefreshToken is false', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('should persist storageCustomParamsAuthRequest when extra custom params given and useRefreshToken is false', async () => {
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const allConfigs = [
|
||||
@ -123,31 +124,31 @@ describe('RefreshSessionService ', () => {
|
||||
silentRenewTimeoutInSeconds: 10,
|
||||
},
|
||||
];
|
||||
const writeSpy = spyOn(storagePersistenceService, 'write');
|
||||
const writeSpy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
const extraCustomParams = { extra: 'custom' };
|
||||
|
||||
refreshSessionService
|
||||
.userForceRefreshSession(allConfigs[0], allConfigs, extraCustomParams)
|
||||
.userForceRefreshSession(allConfigs[0]!, allConfigs, extraCustomParams)
|
||||
.subscribe(() => {
|
||||
expect(writeSpy).toHaveBeenCalledOnceWith(
|
||||
expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageCustomParamsAuthRequest',
|
||||
extraCustomParams,
|
||||
allConfigs[0]
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should NOT persist customparams if no customparams are given', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('should NOT persist customparams if no customparams are given', async () => {
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const allConfigs = [
|
||||
@ -157,20 +158,20 @@ describe('RefreshSessionService ', () => {
|
||||
silentRenewTimeoutInSeconds: 10,
|
||||
},
|
||||
];
|
||||
const writeSpy = spyOn(storagePersistenceService, 'write');
|
||||
const writeSpy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
refreshSessionService
|
||||
.userForceRefreshSession(allConfigs[0], allConfigs)
|
||||
.userForceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe(() => {
|
||||
expect(writeSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should call resetSilentRenewRunning in case of an error', waitForAsync(() => {
|
||||
spyOn(refreshSessionService, 'forceRefreshSession').and.returnValue(
|
||||
it('should call resetSilentRenewRunning in case of an error', async () => {
|
||||
vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
spyOn(flowsDataService, 'resetSilentRenewRunning');
|
||||
vi.spyOn(flowsDataService, 'resetSilentRenewRunning');
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -180,7 +181,7 @@ describe('RefreshSessionService ', () => {
|
||||
];
|
||||
|
||||
refreshSessionService
|
||||
.userForceRefreshSession(allConfigs[0], allConfigs)
|
||||
.userForceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
fail('It should not return any result.');
|
||||
@ -191,16 +192,16 @@ describe('RefreshSessionService ', () => {
|
||||
complete: () => {
|
||||
expect(
|
||||
flowsDataService.resetSilentRenewRunning
|
||||
).toHaveBeenCalledOnceWith(allConfigs[0]);
|
||||
).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should call resetSilentRenewRunning in case of no error', waitForAsync(() => {
|
||||
spyOn(refreshSessionService, 'forceRefreshSession').and.returnValue(
|
||||
it('should call resetSilentRenewRunning in case of no error', async () => {
|
||||
vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
|
||||
of({} as LoginResponse)
|
||||
);
|
||||
spyOn(flowsDataService, 'resetSilentRenewRunning');
|
||||
vi.spyOn(flowsDataService, 'resetSilentRenewRunning');
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -210,7 +211,7 @@ describe('RefreshSessionService ', () => {
|
||||
];
|
||||
|
||||
refreshSessionService
|
||||
.userForceRefreshSession(allConfigs[0], allConfigs)
|
||||
.userForceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
fail('It should not return any error.');
|
||||
@ -218,27 +219,29 @@ describe('RefreshSessionService ', () => {
|
||||
complete: () => {
|
||||
expect(
|
||||
flowsDataService.resetSilentRenewRunning
|
||||
).toHaveBeenCalledOnceWith(allConfigs[0]);
|
||||
).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('forceRefreshSession', () => {
|
||||
it('only calls start refresh session and returns idToken and accessToken if auth is true', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('only calls start refresh session and returns idToken and accessToken if auth is true', async () => {
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
true
|
||||
);
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('id-token');
|
||||
spyOn(authStateService, 'getAccessToken').and.returnValue('access-token');
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('id-token');
|
||||
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
|
||||
'access-token'
|
||||
);
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -247,23 +250,23 @@ describe('RefreshSessionService ', () => {
|
||||
];
|
||||
|
||||
refreshSessionService
|
||||
.forceRefreshSession(allConfigs[0], allConfigs)
|
||||
.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe((result) => {
|
||||
expect(result.idToken).toEqual('id-token');
|
||||
expect(result.accessToken).toEqual('access-token');
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('only calls start refresh session and returns null if auth is false', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('only calls start refresh session and returns null if auth is false', async () => {
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const allConfigs = [
|
||||
@ -274,7 +277,7 @@ describe('RefreshSessionService ', () => {
|
||||
];
|
||||
|
||||
refreshSessionService
|
||||
.forceRefreshSession(allConfigs[0], allConfigs)
|
||||
.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe((result) => {
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
@ -285,24 +288,24 @@ describe('RefreshSessionService ', () => {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls start refresh session and waits for completed, returns idtoken and accesstoken if auth is true', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('calls start refresh session and waits for completed, returns idtoken and accesstoken if auth is true', async () => {
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(false);
|
||||
spyOn(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
true
|
||||
);
|
||||
spyOnProperty(
|
||||
vi.spyOnProperty(
|
||||
silentRenewService,
|
||||
'refreshSessionWithIFrameCompleted$'
|
||||
).and.returnValue(
|
||||
).mockReturnValue(
|
||||
of({
|
||||
authResult: {
|
||||
id_token: 'some-id_token',
|
||||
@ -318,29 +321,29 @@ describe('RefreshSessionService ', () => {
|
||||
];
|
||||
|
||||
refreshSessionService
|
||||
.forceRefreshSession(allConfigs[0], allConfigs)
|
||||
.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe((result) => {
|
||||
expect(result.idToken).toBeDefined();
|
||||
expect(result.accessToken).toBeDefined();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls start refresh session and waits for completed, returns LoginResponse if auth is false', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('calls start refresh session and waits for completed, returns LoginResponse if auth is false', async () => {
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(false);
|
||||
spyOn(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
spyOnProperty(
|
||||
vi.spyOnProperty(
|
||||
silentRenewService,
|
||||
'refreshSessionWithIFrameCompleted$'
|
||||
).and.returnValue(of(null));
|
||||
).mockReturnValue(of(null));
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -349,7 +352,7 @@ describe('RefreshSessionService ', () => {
|
||||
];
|
||||
|
||||
refreshSessionService
|
||||
.forceRefreshSession(allConfigs[0], allConfigs)
|
||||
.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe((result) => {
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
@ -360,23 +363,23 @@ describe('RefreshSessionService ', () => {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('occurs timeout error and retry mechanism exhausted max retry count throws error', fakeAsync(() => {
|
||||
spyOn(
|
||||
it('occurs timeout error and retry mechanism exhausted max retry count throws error', async () => {
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(false);
|
||||
spyOn(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOnProperty(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOnProperty(
|
||||
silentRenewService,
|
||||
'refreshSessionWithIFrameCompleted$'
|
||||
).and.returnValue(of(null).pipe(delay(11000)));
|
||||
).mockReturnValue(of(null).pipe(delay(11000)));
|
||||
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const allConfigs = [
|
||||
@ -386,14 +389,14 @@ describe('RefreshSessionService ', () => {
|
||||
},
|
||||
];
|
||||
|
||||
const resetSilentRenewRunningSpy = spyOn(
|
||||
const resetSilentRenewRunningSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
const expectedInvokeCount = MAX_RETRY_ATTEMPTS;
|
||||
|
||||
refreshSessionService
|
||||
.forceRefreshSession(allConfigs[0], allConfigs)
|
||||
.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
fail('It should not return any result.');
|
||||
@ -407,9 +410,9 @@ describe('RefreshSessionService ', () => {
|
||||
});
|
||||
|
||||
tick(allConfigs[0].silentRenewTimeoutInSeconds * 10000);
|
||||
}));
|
||||
});
|
||||
|
||||
it('occurs unknown error throws it to subscriber', fakeAsync(() => {
|
||||
it('occurs unknown error throws it to subscriber', async () => {
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -419,29 +422,29 @@ describe('RefreshSessionService ', () => {
|
||||
|
||||
const expectedErrorMessage = 'Test error message';
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(false);
|
||||
spyOnProperty(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOnProperty(
|
||||
silentRenewService,
|
||||
'refreshSessionWithIFrameCompleted$'
|
||||
).and.returnValue(of(null));
|
||||
spyOn(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(throwError(() => new Error(expectedErrorMessage)));
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
).mockReturnValue(throwError(() => new Error(expectedErrorMessage)));
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
|
||||
const resetSilentRenewRunningSpy = spyOn(
|
||||
const resetSilentRenewRunningSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
|
||||
refreshSessionService
|
||||
.forceRefreshSession(allConfigs[0], allConfigs)
|
||||
.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
fail('It should not return any result.');
|
||||
@ -452,10 +455,10 @@ describe('RefreshSessionService ', () => {
|
||||
expect(resetSilentRenewRunningSpy).not.toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
describe('NOT isCurrentFlowCodeFlowWithRefreshTokens', () => {
|
||||
it('does return null when not authenticated', waitForAsync(() => {
|
||||
it('does return null when not authenticated', async () => {
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -463,24 +466,24 @@ describe('RefreshSessionService ', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(false);
|
||||
spyOn(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOn(authStateService, 'areAuthStorageTokensValid').and.returnValue(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
false
|
||||
);
|
||||
spyOnProperty(
|
||||
vi.spyOnProperty(
|
||||
silentRenewService,
|
||||
'refreshSessionWithIFrameCompleted$'
|
||||
).and.returnValue(of(null));
|
||||
).mockReturnValue(of(null));
|
||||
|
||||
refreshSessionService
|
||||
.forceRefreshSession(allConfigs[0], allConfigs)
|
||||
.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe((result) => {
|
||||
expect(result).toEqual({
|
||||
isAuthenticated: false,
|
||||
@ -491,9 +494,9 @@ describe('RefreshSessionService ', () => {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('return value only returns once', waitForAsync(() => {
|
||||
it('return value only returns once', async () => {
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -501,18 +504,18 @@ describe('RefreshSessionService ', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(false);
|
||||
spyOn(
|
||||
).mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
refreshSessionService as any,
|
||||
'startRefreshSession'
|
||||
).and.returnValue(of(null));
|
||||
spyOnProperty(
|
||||
).mockReturnValue(of(null));
|
||||
vi.spyOnProperty(
|
||||
silentRenewService,
|
||||
'refreshSessionWithIFrameCompleted$'
|
||||
).and.returnValue(
|
||||
).mockReturnValue(
|
||||
of({
|
||||
authResult: {
|
||||
id_token: 'some-id_token',
|
||||
@ -520,13 +523,12 @@ describe('RefreshSessionService ', () => {
|
||||
},
|
||||
} as CallbackContext)
|
||||
);
|
||||
const spyInsideMap = spyOn(
|
||||
authStateService,
|
||||
'areAuthStorageTokensValid'
|
||||
).and.returnValue(true);
|
||||
const spyInsideMap = vi
|
||||
.spyOn(authStateService, 'areAuthStorageTokensValid')
|
||||
.mockReturnValue(true);
|
||||
|
||||
refreshSessionService
|
||||
.forceRefreshSession(allConfigs[0], allConfigs)
|
||||
.forceRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe((result) => {
|
||||
expect(result).toEqual({
|
||||
idToken: 'some-id_token',
|
||||
@ -537,33 +539,33 @@ describe('RefreshSessionService ', () => {
|
||||
});
|
||||
expect(spyInsideMap).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('startRefreshSession', () => {
|
||||
it('returns null if no auth well known endpoint defined', waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
|
||||
it('returns null if no auth well known endpoint defined', async () => {
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
|
||||
|
||||
(refreshSessionService as any)
|
||||
.startRefreshSession()
|
||||
.subscribe((result: any) => {
|
||||
expect(result).toBe(null);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns null if silent renew Is running', waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
|
||||
it('returns null if silent renew Is running', async () => {
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
|
||||
|
||||
(refreshSessionService as any)
|
||||
.startRefreshSession()
|
||||
.subscribe((result: any) => {
|
||||
expect(result).toBe(null);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls `setSilentRenewRunning` when should be executed', waitForAsync(() => {
|
||||
const setSilentRenewRunningSpy = spyOn(
|
||||
it('calls `setSilentRenewRunning` when should be executed', async () => {
|
||||
const setSilentRenewRunningSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'setSilentRenewRunning'
|
||||
);
|
||||
@ -574,30 +576,30 @@ describe('RefreshSessionService ', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
).mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
(refreshSessionService as any)
|
||||
.startRefreshSession(allConfigs[0], allConfigs)
|
||||
.startRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe(() => {
|
||||
expect(setSilentRenewRunningSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls refreshSessionWithRefreshTokens when current flow is codeflow with refresh tokens', waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'setSilentRenewRunning');
|
||||
it('calls refreshSessionWithRefreshTokens when current flow is codeflow with refresh tokens', async () => {
|
||||
vi.spyOn(flowsDataService, 'setSilentRenewRunning');
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -605,30 +607,32 @@ describe('RefreshSessionService ', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(true);
|
||||
const refreshSessionWithRefreshTokensSpy = spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
).mockReturnValue(true);
|
||||
const refreshSessionWithRefreshTokensSpy = vi
|
||||
.spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
)
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
(refreshSessionService as any)
|
||||
.startRefreshSession(allConfigs[0], allConfigs)
|
||||
.startRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe(() => {
|
||||
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls refreshSessionWithIframe when current flow is NOT codeflow with refresh tokens', waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'setSilentRenewRunning');
|
||||
it('calls refreshSessionWithIframe when current flow is NOT codeflow with refresh tokens', async () => {
|
||||
vi.spyOn(flowsDataService, 'setSilentRenewRunning');
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -636,32 +640,33 @@ describe('RefreshSessionService ', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
spyOn(
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlowWithRefreshTokens'
|
||||
).and.returnValue(false);
|
||||
const refreshSessionWithRefreshTokensSpy = spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
).mockReturnValue(false);
|
||||
const refreshSessionWithRefreshTokensSpy = vi
|
||||
.spyOn(
|
||||
refreshSessionRefreshTokenService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
)
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
|
||||
const refreshSessionWithIframeSpy = spyOn(
|
||||
refreshSessionIframeService,
|
||||
'refreshSessionWithIframe'
|
||||
).and.returnValue(of(false));
|
||||
const refreshSessionWithIframeSpy = vi
|
||||
.spyOn(refreshSessionIframeService, 'refreshSessionWithIframe')
|
||||
.mockReturnValue(of(false));
|
||||
|
||||
(refreshSessionService as any)
|
||||
.startRefreshSession(allConfigs[0], allConfigs)
|
||||
.startRefreshSession(allConfigs[0]!, allConfigs)
|
||||
.subscribe(() => {
|
||||
expect(refreshSessionWithRefreshTokensSpy).not.toHaveBeenCalled();
|
||||
expect(refreshSessionWithIframeSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import {
|
||||
type Observable,
|
||||
TimeoutError,
|
||||
forkJoin,
|
||||
Observable,
|
||||
of,
|
||||
throwError,
|
||||
TimeoutError,
|
||||
timer,
|
||||
} from 'rxjs';
|
||||
import {
|
||||
@ -18,13 +18,13 @@ import {
|
||||
} from 'rxjs/operators';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { AuthWellKnownService } from '../config/auth-well-known/auth-well-known.service';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { RefreshSessionIframeService } from '../iframe/refresh-session-iframe.service';
|
||||
import { SilentRenewService } from '../iframe/silent-renew.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { LoginResponse } from '../login/login-response';
|
||||
import type { LoginResponse } from '../login/login-response';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { UserService } from '../user-data/user.service';
|
||||
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { createRetriableStream } from '../../../test/create-retriable-stream.helper';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { createRetriableStream } from '../../testing/create-retriable-stream.helper';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { AuthWellKnownDataService } from './auth-well-known-data.service';
|
||||
import { AuthWellKnownEndpoints } from './auth-well-known-endpoints';
|
||||
import type { AuthWellKnownEndpoints } from './auth-well-known-endpoints';
|
||||
|
||||
const DUMMY_WELL_KNOWN_DOCUMENT = {
|
||||
issuer: 'https://identity-server.test/realms/main',
|
||||
@ -51,56 +52,65 @@ describe('AuthWellKnownDataService', () => {
|
||||
});
|
||||
|
||||
describe('getWellKnownDocument', () => {
|
||||
it('should add suffix if it does not exist on current URL', waitForAsync(() => {
|
||||
const dataServiceSpy = spyOn(dataService, 'get').and.returnValue(
|
||||
of(null)
|
||||
);
|
||||
it('should add suffix if it does not exist on current URL', async () => {
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'get')
|
||||
.mockReturnValue(of(null));
|
||||
const urlWithoutSuffix = 'myUrl';
|
||||
const urlWithSuffix = `${urlWithoutSuffix}/.well-known/openid-configuration`;
|
||||
|
||||
(service as any)
|
||||
.getWellKnownDocument(urlWithoutSuffix, { configId: 'configId1' })
|
||||
.subscribe(() => {
|
||||
expect(dataServiceSpy).toHaveBeenCalledOnceWith(urlWithSuffix, {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
urlWithSuffix,
|
||||
{
|
||||
configId: 'configId1',
|
||||
}
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not add suffix if it does exist on current url', waitForAsync(() => {
|
||||
const dataServiceSpy = spyOn(dataService, 'get').and.returnValue(
|
||||
of(null)
|
||||
);
|
||||
it('should not add suffix if it does exist on current url', async () => {
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'get')
|
||||
.mockReturnValue(of(null));
|
||||
const urlWithSuffix = `myUrl/.well-known/openid-configuration`;
|
||||
|
||||
(service as any)
|
||||
.getWellKnownDocument(urlWithSuffix, { configId: 'configId1' })
|
||||
.subscribe(() => {
|
||||
expect(dataServiceSpy).toHaveBeenCalledOnceWith(urlWithSuffix, {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
urlWithSuffix,
|
||||
{
|
||||
configId: 'configId1',
|
||||
}
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not add suffix if it does exist in the middle of current url', waitForAsync(() => {
|
||||
const dataServiceSpy = spyOn(dataService, 'get').and.returnValue(
|
||||
of(null)
|
||||
);
|
||||
it('should not add suffix if it does exist in the middle of current url', async () => {
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'get')
|
||||
.mockReturnValue(of(null));
|
||||
const urlWithSuffix = `myUrl/.well-known/openid-configuration/and/some/more/stuff`;
|
||||
|
||||
(service as any)
|
||||
.getWellKnownDocument(urlWithSuffix, { configId: 'configId1' })
|
||||
.subscribe(() => {
|
||||
expect(dataServiceSpy).toHaveBeenCalledOnceWith(urlWithSuffix, {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
urlWithSuffix,
|
||||
{
|
||||
configId: 'configId1',
|
||||
}
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should use the custom suffix provided in the config', waitForAsync(() => {
|
||||
const dataServiceSpy = spyOn(dataService, 'get').and.returnValue(
|
||||
of(null)
|
||||
);
|
||||
it('should use the custom suffix provided in the config', async () => {
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'get')
|
||||
.mockReturnValue(of(null));
|
||||
const urlWithoutSuffix = `myUrl`;
|
||||
const urlWithSuffix = `${urlWithoutSuffix}/.well-known/test-openid-configuration`;
|
||||
|
||||
@ -110,15 +120,18 @@ describe('AuthWellKnownDataService', () => {
|
||||
authWellknownUrlSuffix: '/.well-known/test-openid-configuration',
|
||||
})
|
||||
.subscribe(() => {
|
||||
expect(dataServiceSpy).toHaveBeenCalledOnceWith(urlWithSuffix, {
|
||||
configId: 'configId1',
|
||||
authWellknownUrlSuffix: '/.well-known/test-openid-configuration',
|
||||
});
|
||||
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
urlWithSuffix,
|
||||
{
|
||||
configId: 'configId1',
|
||||
authWellknownUrlSuffix: '/.well-known/test-openid-configuration',
|
||||
}
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry once', waitForAsync(() => {
|
||||
spyOn(dataService, 'get').and.returnValue(
|
||||
it('should retry once', async () => {
|
||||
vi.spyOn(dataService, 'get').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('one')),
|
||||
of(DUMMY_WELL_KNOWN_DOCUMENT)
|
||||
@ -133,10 +146,10 @@ describe('AuthWellKnownDataService', () => {
|
||||
expect(res).toEqual(DUMMY_WELL_KNOWN_DOCUMENT);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry twice', waitForAsync(() => {
|
||||
spyOn(dataService, 'get').and.returnValue(
|
||||
it('should retry twice', async () => {
|
||||
vi.spyOn(dataService, 'get').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('one')),
|
||||
throwError(() => new Error('two')),
|
||||
@ -152,10 +165,10 @@ describe('AuthWellKnownDataService', () => {
|
||||
expect(res).toEqual(DUMMY_WELL_KNOWN_DOCUMENT);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should fail after three tries', waitForAsync(() => {
|
||||
spyOn(dataService, 'get').and.returnValue(
|
||||
it('should fail after three tries', async () => {
|
||||
vi.spyOn(dataService, 'get').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('one')),
|
||||
throwError(() => new Error('two')),
|
||||
@ -169,17 +182,16 @@ describe('AuthWellKnownDataService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('getWellKnownEndPointsForConfig', () => {
|
||||
it('calling internal getWellKnownDocument and maps', waitForAsync(() => {
|
||||
spyOn(dataService, 'get').and.returnValue(of({ jwks_uri: 'jwks_uri' }));
|
||||
it('calling internal getWellKnownDocument and maps', async () => {
|
||||
vi.spyOn(dataService, 'get').mockReturnValue(
|
||||
of({ jwks_uri: 'jwks_uri' })
|
||||
);
|
||||
|
||||
const spy = spyOn(
|
||||
service as any,
|
||||
'getWellKnownDocument'
|
||||
).and.callThrough();
|
||||
const spy = vi.spyOn(service as any, 'getWellKnownDocument')();
|
||||
|
||||
service
|
||||
.getWellKnownEndPointsForConfig({
|
||||
@ -191,10 +203,10 @@ describe('AuthWellKnownDataService', () => {
|
||||
expect((result as any).jwks_uri).toBeUndefined();
|
||||
expect(result.jwksUri).toBe('jwks_uri');
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws error and logs if no authwellknownUrl is given', waitForAsync(() => {
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
it('throws error and logs if no authwellknownUrl is given', async () => {
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
authWellknownEndpointUrl: undefined,
|
||||
@ -202,17 +214,19 @@ describe('AuthWellKnownDataService', () => {
|
||||
|
||||
service.getWellKnownEndPointsForConfig(config).subscribe({
|
||||
error: (error) => {
|
||||
expect(loggerSpy).toHaveBeenCalledOnceWith(
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
'no authWellknownEndpoint given!'
|
||||
);
|
||||
expect(error.message).toEqual('no authWellknownEndpoint given!');
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should merge the mapped endpoints with the provided endpoints', waitForAsync(() => {
|
||||
spyOn(dataService, 'get').and.returnValue(of(DUMMY_WELL_KNOWN_DOCUMENT));
|
||||
it('should merge the mapped endpoints with the provided endpoints', async () => {
|
||||
vi.spyOn(dataService, 'get').mockReturnValue(
|
||||
of(DUMMY_WELL_KNOWN_DOCUMENT)
|
||||
);
|
||||
|
||||
const expected: AuthWellKnownEndpoints = {
|
||||
endSessionEndpoint: 'config-endSessionEndpoint',
|
||||
@ -232,6 +246,6 @@ describe('AuthWellKnownDataService', () => {
|
||||
.subscribe((result) => {
|
||||
expect(result).toEqual(jasmine.objectContaining(expected));
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { EventTypes } from '../../public-events/event-types';
|
||||
import { PublicEventsService } from '../../public-events/public-events.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { AuthWellKnownDataService } from './auth-well-known-data.service';
|
||||
import { AuthWellKnownService } from './auth-well-known.service';
|
||||
|
||||
@ -22,9 +23,6 @@ describe('AuthWellKnownService', () => {
|
||||
mockProvider(StoragePersistenceService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(AuthWellKnownService);
|
||||
dataService = TestBed.inject(AuthWellKnownDataService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
@ -36,7 +34,7 @@ describe('AuthWellKnownService', () => {
|
||||
});
|
||||
|
||||
describe('getAuthWellKnownEndPoints', () => {
|
||||
it('getAuthWellKnownEndPoints throws an error if not config provided', waitForAsync(() => {
|
||||
it('getAuthWellKnownEndPoints throws an error if not config provided', async () => {
|
||||
service.queryAndStoreAuthWellKnownEndPoints(null).subscribe({
|
||||
error: (error) => {
|
||||
expect(error).toEqual(
|
||||
@ -46,17 +44,18 @@ describe('AuthWellKnownService', () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('getAuthWellKnownEndPoints calls always dataservice', waitForAsync(() => {
|
||||
const dataServiceSpy = spyOn(
|
||||
dataService,
|
||||
'getWellKnownEndPointsForConfig'
|
||||
).and.returnValue(of({ issuer: 'anything' }));
|
||||
it('getAuthWellKnownEndPoints calls always dataservice', async () => {
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'getWellKnownEndPointsForConfig')
|
||||
.mockReturnValue(of({ issuer: 'anything' }));
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ issuer: 'anything' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ issuer: 'anything' })
|
||||
);
|
||||
|
||||
service
|
||||
.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
|
||||
@ -65,18 +64,19 @@ describe('AuthWellKnownService', () => {
|
||||
expect(dataServiceSpy).toHaveBeenCalled();
|
||||
expect(result).toEqual({ issuer: 'anything' });
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('getAuthWellKnownEndPoints stored the result if http call is made', waitForAsync(() => {
|
||||
const dataServiceSpy = spyOn(
|
||||
dataService,
|
||||
'getWellKnownEndPointsForConfig'
|
||||
).and.returnValue(of({ issuer: 'anything' }));
|
||||
it('getAuthWellKnownEndPoints stored the result if http call is made', async () => {
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'getWellKnownEndPointsForConfig')
|
||||
.mockReturnValue(of({ issuer: 'anything' }));
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue(null);
|
||||
const storeSpy = spyOn(service, 'storeWellKnownEndpoints');
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => null
|
||||
);
|
||||
const storeSpy = vi.spyOn(service, 'storeWellKnownEndpoints');
|
||||
|
||||
service
|
||||
.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
|
||||
@ -85,13 +85,13 @@ describe('AuthWellKnownService', () => {
|
||||
expect(storeSpy).toHaveBeenCalled();
|
||||
expect(result).toEqual({ issuer: 'anything' });
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws `ConfigLoadingFailed` event when error happens from http', waitForAsync(() => {
|
||||
spyOn(dataService, 'getWellKnownEndPointsForConfig').and.returnValue(
|
||||
it('throws `ConfigLoadingFailed` event when error happens from http', async () => {
|
||||
vi.spyOn(dataService, 'getWellKnownEndPointsForConfig').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
const publicEventsServiceSpy = spyOn(publicEventsService, 'fireEvent');
|
||||
const publicEventsServiceSpy = vi.spyOn(publicEventsService, 'fireEvent');
|
||||
|
||||
service
|
||||
.queryAndStoreAuthWellKnownEndPoints({ configId: 'configId1' })
|
||||
@ -99,12 +99,12 @@ describe('AuthWellKnownService', () => {
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
expect(publicEventsServiceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(publicEventsServiceSpy).toHaveBeenCalledOnceWith(
|
||||
expect(publicEventsServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
EventTypes.ConfigLoadingFailed,
|
||||
null
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockAbstractProvider, mockProvider } from '../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { EventTypes } from '../public-events/event-types';
|
||||
import { PublicEventsService } from '../public-events/public-events.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { mockAbstractProvider, mockProvider } from '../testing/mock';
|
||||
import { PlatformProvider } from '../utils/platform-provider/platform.provider';
|
||||
import { AuthWellKnownService } from './auth-well-known/auth-well-known.service';
|
||||
import { ConfigurationService } from './config.service';
|
||||
import { StsConfigLoader, StsConfigStaticLoader } from './loader/config-loader';
|
||||
import { OpenIdConfiguration } from './openid-configuration';
|
||||
import type { OpenIdConfiguration } from './openid-configuration';
|
||||
import { ConfigValidationService } from './validation/config-validation.service';
|
||||
|
||||
describe('Configuration Service', () => {
|
||||
@ -34,9 +35,6 @@ describe('Configuration Service', () => {
|
||||
mockAbstractProvider(StsConfigLoader, StsConfigStaticLoader),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
configService = TestBed.inject(ConfigurationService);
|
||||
publicEventsService = TestBed.inject(PublicEventsService);
|
||||
authWellKnownService = TestBed.inject(AuthWellKnownService);
|
||||
@ -88,47 +86,53 @@ describe('Configuration Service', () => {
|
||||
});
|
||||
|
||||
describe('getOpenIDConfiguration', () => {
|
||||
it(`if config is already saved 'loadConfigs' is not called`, waitForAsync(() => {
|
||||
it(`if config is already saved 'loadConfigs' is not called`, async () => {
|
||||
(configService as any).configsInternal = {
|
||||
configId1: { configId: 'configId1' },
|
||||
configId2: { configId: 'configId2' },
|
||||
};
|
||||
const spy = spyOn(configService as any, 'loadConfigs');
|
||||
const spy = vi.spyOn(configService as any, 'loadConfigs');
|
||||
|
||||
configService.getOpenIDConfiguration('configId1').subscribe((config) => {
|
||||
expect(config).toBeTruthy();
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`if config is NOT already saved 'loadConfigs' is called`, waitForAsync(() => {
|
||||
it(`if config is NOT already saved 'loadConfigs' is called`, async () => {
|
||||
const configs = [{ configId: 'configId1' }, { configId: 'configId2' }];
|
||||
const spy = spyOn(configService as any, 'loadConfigs').and.returnValue(
|
||||
of(configs)
|
||||
);
|
||||
const spy = vi
|
||||
.spyOn(configService as any, 'loadConfigs')
|
||||
.mockReturnValue(of(configs));
|
||||
|
||||
spyOn(configValidationService, 'validateConfig').and.returnValue(true);
|
||||
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
|
||||
|
||||
configService.getOpenIDConfiguration('configId1').subscribe((config) => {
|
||||
expect(config).toBeTruthy();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`returns null if config is not valid`, waitForAsync(() => {
|
||||
it('returns null if config is not valid', async () => {
|
||||
const configs = [{ configId: 'configId1' }];
|
||||
|
||||
spyOn(configService as any, 'loadConfigs').and.returnValue(of(configs));
|
||||
spyOn(configValidationService, 'validateConfig').and.returnValue(false);
|
||||
const consoleSpy = spyOn(console, 'warn');
|
||||
vi.spyOn(configService as any, 'loadConfigs').mockReturnValue(
|
||||
of(configs)
|
||||
);
|
||||
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const consoleSpy = vi.spyOn(console, 'warn');
|
||||
|
||||
configService.getOpenIDConfiguration('configId1').subscribe((config) => {
|
||||
expect(config).toBeNull();
|
||||
expect(consoleSpy).toHaveBeenCalledOnceWith(`[oidc-client-rx] No configuration found for config id 'configId1'.`)
|
||||
expect(consoleSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
`[oidc-client-rx] No configuration found for config id 'configId1'.`
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`returns null if configs are stored but not existing ID is passed`, waitForAsync(() => {
|
||||
it('returns null if configs are stored but not existing ID is passed', async () => {
|
||||
(configService as any).configsInternal = {
|
||||
configId1: { configId: 'configId1' },
|
||||
configId2: { configId: 'configId2' },
|
||||
@ -139,16 +143,18 @@ describe('Configuration Service', () => {
|
||||
.subscribe((config) => {
|
||||
expect(config).toBeNull();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`sets authWellKnownEndPoints on config if authWellKnownEndPoints is stored`, waitForAsync(() => {
|
||||
it('sets authWellKnownEndPoints on config if authWellKnownEndPoints is stored', async () => {
|
||||
const configs = [{ configId: 'configId1' }];
|
||||
|
||||
spyOn(configService as any, 'loadConfigs').and.returnValue(of(configs));
|
||||
spyOn(configValidationService, 'validateConfig').and.returnValue(true);
|
||||
const consoleSpy = spyOn(console, 'warn');
|
||||
vi.spyOn(configService as any, 'loadConfigs').mockReturnValue(
|
||||
of(configs)
|
||||
);
|
||||
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
|
||||
const consoleSpy = vi.spyOn(console, 'warn');
|
||||
|
||||
spyOn(storagePersistenceService, 'read').and.returnValue({
|
||||
vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
|
||||
issuer: 'auth-well-known',
|
||||
});
|
||||
|
||||
@ -156,30 +162,32 @@ describe('Configuration Service', () => {
|
||||
expect(config?.authWellknownEndpoints).toEqual({
|
||||
issuer: 'auth-well-known',
|
||||
});
|
||||
expect(consoleSpy).not.toHaveBeenCalled()
|
||||
expect(consoleSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`fires ConfigLoaded if authWellKnownEndPoints is stored`, waitForAsync(() => {
|
||||
it('fires ConfigLoaded if authWellKnownEndPoints is stored', async () => {
|
||||
const configs = [{ configId: 'configId1' }];
|
||||
|
||||
spyOn(configService as any, 'loadConfigs').and.returnValue(of(configs));
|
||||
spyOn(configValidationService, 'validateConfig').and.returnValue(true);
|
||||
spyOn(storagePersistenceService, 'read').and.returnValue({
|
||||
vi.spyOn(configService as any, 'loadConfigs').mockReturnValue(
|
||||
of(configs)
|
||||
);
|
||||
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
|
||||
vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
|
||||
issuer: 'auth-well-known',
|
||||
});
|
||||
|
||||
const spy = spyOn(publicEventsService, 'fireEvent');
|
||||
const spy = vi.spyOn(publicEventsService, 'fireEvent');
|
||||
|
||||
configService.getOpenIDConfiguration('configId1').subscribe(() => {
|
||||
expect(spy).toHaveBeenCalledOnceWith(
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
EventTypes.ConfigLoaded,
|
||||
jasmine.anything()
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`stores, uses and fires event when authwellknownendpoints are passed`, waitForAsync(() => {
|
||||
it('stores, uses and fires event when authwellknownendpoints are passed', async () => {
|
||||
const configs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -187,58 +195,60 @@ describe('Configuration Service', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(configService as any, 'loadConfigs').and.returnValue(of(configs));
|
||||
spyOn(configValidationService, 'validateConfig').and.returnValue(true);
|
||||
spyOn(storagePersistenceService, 'read').and.returnValue(null);
|
||||
vi.spyOn(configService as any, 'loadConfigs').mockReturnValue(
|
||||
of(configs)
|
||||
);
|
||||
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
|
||||
vi.spyOn(storagePersistenceService, 'read').mockReturnValue(null);
|
||||
|
||||
const fireEventSpy = spyOn(publicEventsService, 'fireEvent');
|
||||
const storeWellKnownEndpointsSpy = spyOn(
|
||||
const fireEventSpy = vi.spyOn(publicEventsService, 'fireEvent');
|
||||
const storeWellKnownEndpointsSpy = vi.spyOn(
|
||||
authWellKnownService,
|
||||
'storeWellKnownEndpoints'
|
||||
);
|
||||
|
||||
configService.getOpenIDConfiguration('configId1').subscribe((config) => {
|
||||
expect(config).toBeTruthy();
|
||||
expect(fireEventSpy).toHaveBeenCalledOnceWith(
|
||||
expect(fireEventSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
EventTypes.ConfigLoaded,
|
||||
jasmine.anything()
|
||||
expect.anything()
|
||||
);
|
||||
expect(storeWellKnownEndpointsSpy).toHaveBeenCalledOnceWith(
|
||||
expect(storeWellKnownEndpointsSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config as OpenIdConfiguration,
|
||||
{
|
||||
issuer: 'auth-well-known',
|
||||
}
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('getOpenIDConfigurations', () => {
|
||||
it(`returns correct result`, waitForAsync(() => {
|
||||
spyOn(stsConfigLoader, 'loadConfigs').and.returnValue(
|
||||
it('returns correct result', async () => {
|
||||
vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue(
|
||||
of([
|
||||
{ configId: 'configId1' } as OpenIdConfiguration,
|
||||
{ configId: 'configId2' } as OpenIdConfiguration,
|
||||
])
|
||||
);
|
||||
|
||||
spyOn(configValidationService, 'validateConfig').and.returnValue(true);
|
||||
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
|
||||
|
||||
configService.getOpenIDConfigurations('configId1').subscribe((result) => {
|
||||
expect(result.allConfigs.length).toEqual(2);
|
||||
expect(result.currentConfig).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`created configId when configId is not set`, waitForAsync(() => {
|
||||
spyOn(stsConfigLoader, 'loadConfigs').and.returnValue(
|
||||
it('created configId when configId is not set', async () => {
|
||||
vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue(
|
||||
of([
|
||||
{ clientId: 'clientId1' } as OpenIdConfiguration,
|
||||
{ clientId: 'clientId2' } as OpenIdConfiguration,
|
||||
])
|
||||
);
|
||||
|
||||
spyOn(configValidationService, 'validateConfig').and.returnValue(true);
|
||||
vi.spyOn(configValidationService, 'validateConfig').mockReturnValue(true);
|
||||
|
||||
configService.getOpenIDConfigurations().subscribe((result) => {
|
||||
expect(result.allConfigs.length).toEqual(2);
|
||||
@ -249,17 +259,19 @@ describe('Configuration Service', () => {
|
||||
expect(result.currentConfig).toBeTruthy();
|
||||
expect(result.currentConfig?.configId).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it(`returns empty array if config is not valid`, waitForAsync(() => {
|
||||
spyOn(stsConfigLoader, 'loadConfigs').and.returnValue(
|
||||
it('returns empty array if config is not valid', async () => {
|
||||
vi.spyOn(stsConfigLoader, 'loadConfigs').mockReturnValue(
|
||||
of([
|
||||
{ configId: 'configId1' } as OpenIdConfiguration,
|
||||
{ configId: 'configId2' } as OpenIdConfiguration,
|
||||
])
|
||||
);
|
||||
|
||||
spyOn(configValidationService, 'validateConfigs').and.returnValue(false);
|
||||
vi.spyOn(configValidationService, 'validateConfigs').mockReturnValue(
|
||||
false
|
||||
);
|
||||
|
||||
configService
|
||||
.getOpenIDConfigurations()
|
||||
@ -267,12 +279,12 @@ describe('Configuration Service', () => {
|
||||
expect(allConfigs).toEqual([]);
|
||||
expect(currentConfig).toBeNull();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('setSpecialCases', () => {
|
||||
it(`should set special cases when current platform is browser`, () => {
|
||||
spyOn(platformProvider, 'isBrowser').and.returnValue(false);
|
||||
it('should set special cases when current platform is browser', () => {
|
||||
vi.spyOn(platformProvider, 'isBrowser').mockReturnValue(false);
|
||||
|
||||
const config = { configId: 'configId1' } as OpenIdConfiguration;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import {inject, Injectable, isDevMode} from 'injection-js';
|
||||
import { forkJoin, Observable, of } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, forkJoin, of } from 'rxjs';
|
||||
import { concatMap, map } from 'rxjs/operators';
|
||||
import { injectAbstractType } from '../injection/inject';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { EventTypes } from '../public-events/event-types';
|
||||
import { PublicEventsService } from '../public-events/public-events.service';
|
||||
@ -9,7 +10,7 @@ import { PlatformProvider } from '../utils/platform-provider/platform.provider';
|
||||
import { AuthWellKnownService } from './auth-well-known/auth-well-known.service';
|
||||
import { DEFAULT_CONFIG } from './default-config';
|
||||
import { StsConfigLoader } from './loader/config-loader';
|
||||
import { OpenIdConfiguration } from './openid-configuration';
|
||||
import type { OpenIdConfiguration } from './openid-configuration';
|
||||
import { ConfigValidationService } from './validation/config-validation.service';
|
||||
|
||||
@Injectable()
|
||||
@ -26,7 +27,7 @@ export class ConfigurationService {
|
||||
|
||||
private readonly authWellKnownService = inject(AuthWellKnownService);
|
||||
|
||||
private readonly loader = inject(StsConfigLoader);
|
||||
private readonly loader = injectAbstractType(StsConfigLoader);
|
||||
|
||||
private readonly configValidationService = inject(ConfigValidationService);
|
||||
|
||||
@ -84,11 +85,14 @@ export class ConfigurationService {
|
||||
}
|
||||
|
||||
private getConfig(configId?: string): OpenIdConfiguration | null {
|
||||
if (Boolean(configId)) {
|
||||
if (configId) {
|
||||
const config = this.configsInternal[configId!];
|
||||
|
||||
if(!config && isDevMode()) {
|
||||
console.warn(`[oidc-client-rx] No configuration found for config id '${configId}'.`);
|
||||
if (!config) {
|
||||
// biome-ignore lint/suspicious/noConsole: <explanation>
|
||||
console.warn(
|
||||
`[oidc-client-rx] No configuration found for config id '${configId}'.`
|
||||
);
|
||||
}
|
||||
|
||||
return config || null;
|
||||
@ -165,7 +169,7 @@ export class ConfigurationService {
|
||||
configuration
|
||||
);
|
||||
|
||||
if (!!alreadyExistingAuthWellKnownEndpoints) {
|
||||
if (alreadyExistingAuthWellKnownEndpoints) {
|
||||
configuration.authWellknownEndpoints =
|
||||
alreadyExistingAuthWellKnownEndpoints;
|
||||
|
||||
@ -174,7 +178,7 @@ export class ConfigurationService {
|
||||
|
||||
const passedAuthWellKnownEndpoints = configuration.authWellknownEndpoints;
|
||||
|
||||
if (!!passedAuthWellKnownEndpoints) {
|
||||
if (passedAuthWellKnownEndpoints) {
|
||||
this.authWellKnownService.storeWellKnownEndpoints(
|
||||
configuration,
|
||||
passedAuthWellKnownEndpoints
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { waitForAsync } from '@angular/core/testing';
|
||||
import { waitForAsync } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { OpenIdConfiguration } from '../openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
import { StsConfigHttpLoader, StsConfigStaticLoader } from './config-loader';
|
||||
|
||||
describe('ConfigLoader', () => {
|
||||
describe('StsConfigStaticLoader', () => {
|
||||
describe('loadConfigs', () => {
|
||||
it('returns an array if an array is passed', waitForAsync(() => {
|
||||
it('returns an array if an array is passed', async () => {
|
||||
const toPass = [
|
||||
{ configId: 'configId1' } as OpenIdConfiguration,
|
||||
{ configId: 'configId2' } as OpenIdConfiguration,
|
||||
@ -17,11 +17,11 @@ describe('ConfigLoader', () => {
|
||||
const result$ = loader.loadConfigs();
|
||||
|
||||
result$.subscribe((result) => {
|
||||
expect(Array.isArray(result)).toBeTrue();
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns an array if only one config is passed', waitForAsync(() => {
|
||||
it('returns an array if only one config is passed', async () => {
|
||||
const loader = new StsConfigStaticLoader({
|
||||
configId: 'configId1',
|
||||
} as OpenIdConfiguration);
|
||||
@ -29,15 +29,15 @@ describe('ConfigLoader', () => {
|
||||
const result$ = loader.loadConfigs();
|
||||
|
||||
result$.subscribe((result) => {
|
||||
expect(Array.isArray(result)).toBeTrue();
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('StsConfigHttpLoader', () => {
|
||||
describe('loadConfigs', () => {
|
||||
it('returns an array if an array of observables is passed', waitForAsync(() => {
|
||||
it('returns an array if an array of observables is passed', async () => {
|
||||
const toPass = [
|
||||
of({ configId: 'configId1' } as OpenIdConfiguration),
|
||||
of({ configId: 'configId2' } as OpenIdConfiguration),
|
||||
@ -47,13 +47,13 @@ describe('ConfigLoader', () => {
|
||||
const result$ = loader.loadConfigs();
|
||||
|
||||
result$.subscribe((result) => {
|
||||
expect(Array.isArray(result)).toBeTrue();
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result[0].configId).toBe('configId1');
|
||||
expect(result[1].configId).toBe('configId2');
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns an array if an observable with a config array is passed', waitForAsync(() => {
|
||||
it('returns an array if an observable with a config array is passed', async () => {
|
||||
const toPass = of([
|
||||
{ configId: 'configId1' } as OpenIdConfiguration,
|
||||
{ configId: 'configId2' } as OpenIdConfiguration,
|
||||
@ -63,13 +63,13 @@ describe('ConfigLoader', () => {
|
||||
const result$ = loader.loadConfigs();
|
||||
|
||||
result$.subscribe((result) => {
|
||||
expect(Array.isArray(result)).toBeTrue();
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result[0].configId).toBe('configId1');
|
||||
expect(result[1].configId).toBe('configId2');
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns an array if only one config is passed', waitForAsync(() => {
|
||||
it('returns an array if only one config is passed', async () => {
|
||||
const loader = new StsConfigHttpLoader(
|
||||
of({ configId: 'configId1' } as OpenIdConfiguration)
|
||||
);
|
||||
@ -77,10 +77,10 @@ describe('ConfigLoader', () => {
|
||||
const result$ = loader.loadConfigs();
|
||||
|
||||
result$.subscribe((result) => {
|
||||
expect(Array.isArray(result)).toBeTrue();
|
||||
expect(Array.isArray(result)).toBeTruthy();
|
||||
expect(result[0].configId).toBe('configId1');
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Provider } from 'injection-js';
|
||||
import { forkJoin, Observable, of } from 'rxjs';
|
||||
import type { Provider } from 'injection-js';
|
||||
import { type Observable, forkJoin, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { OpenIdConfiguration } from '../openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
|
||||
export class OpenIdConfigLoader {
|
||||
loader?: Provider;
|
||||
@ -13,6 +13,7 @@ export abstract class StsConfigLoader {
|
||||
|
||||
export class StsConfigStaticLoader implements StsConfigLoader {
|
||||
constructor(
|
||||
// biome-ignore lint/style/noParameterProperties: <explanation>
|
||||
private readonly passedConfigs: OpenIdConfiguration | OpenIdConfiguration[]
|
||||
) {}
|
||||
|
||||
@ -27,6 +28,7 @@ export class StsConfigStaticLoader implements StsConfigLoader {
|
||||
|
||||
export class StsConfigHttpLoader implements StsConfigLoader {
|
||||
constructor(
|
||||
// biome-ignore lint/style/noParameterProperties: <explanation>
|
||||
private readonly configs$:
|
||||
| Observable<OpenIdConfiguration>
|
||||
| Observable<OpenIdConfiguration>[]
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { LogLevel } from '../logging/log-level';
|
||||
import { AuthWellKnownEndpoints } from './auth-well-known/auth-well-known-endpoints';
|
||||
import type { LogLevel } from '../logging/log-level';
|
||||
import type { AuthWellKnownEndpoints } from './auth-well-known/auth-well-known-endpoints';
|
||||
|
||||
export interface OpenIdConfiguration {
|
||||
/**
|
||||
@ -207,5 +207,5 @@ export interface OpenIdConfiguration {
|
||||
/**
|
||||
* Disable cleaning up the popup when receiving invalid messages
|
||||
*/
|
||||
disableCleaningPopupOnInvalidMessage?: boolean
|
||||
disableCleaningPopupOnInvalidMessage?: boolean;
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LogLevel } from '../../logging/log-level';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { OpenIdConfiguration } from '../openid-configuration';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
import { ConfigValidationService } from './config-validation.service';
|
||||
import { allMultipleConfigRules } from './rules';
|
||||
|
||||
@ -14,6 +15,8 @@ describe('Config Validation Service', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [ConfigValidationService, mockProvider(LoggerService)],
|
||||
});
|
||||
configValidationService = TestBed.inject(ConfigValidationService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
});
|
||||
|
||||
const VALID_CONFIG = {
|
||||
@ -29,11 +32,6 @@ describe('Config Validation Service', () => {
|
||||
logLevel: LogLevel.Debug,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
configValidationService = TestBed.inject(ConfigValidationService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(configValidationService).toBeTruthy();
|
||||
});
|
||||
@ -42,26 +40,27 @@ describe('Config Validation Service', () => {
|
||||
const config = {};
|
||||
const result = configValidationService.validateConfig(config);
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return true for valid config', () => {
|
||||
const result = configValidationService.validateConfig(VALID_CONFIG);
|
||||
|
||||
expect(result).toBeTrue();
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('calls `logWarning` if one rule has warning level', () => {
|
||||
const loggerWarningSpy = spyOn(loggerService, 'logWarning');
|
||||
const messageTypeSpy = spyOn(
|
||||
const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
|
||||
const messageTypeSpy = vi.spyOn(
|
||||
configValidationService as any,
|
||||
'getAllMessagesOfType'
|
||||
);
|
||||
|
||||
messageTypeSpy
|
||||
.withArgs('warning', jasmine.any(Array))
|
||||
.and.returnValue(['A warning message']);
|
||||
messageTypeSpy.withArgs('error', jasmine.any(Array)).and.callThrough();
|
||||
mockImplementationWhenArgsEqual(
|
||||
messageTypeSpy,
|
||||
(arg1: any, arg2: any) => arg1 === 'warning' && Array.isArray(arg2),
|
||||
() => ['A warning message']
|
||||
);
|
||||
|
||||
configValidationService.validateConfig(VALID_CONFIG);
|
||||
expect(loggerWarningSpy).toHaveBeenCalled();
|
||||
@ -72,7 +71,7 @@ describe('Config Validation Service', () => {
|
||||
const config = { ...VALID_CONFIG, clientId: '' } as OpenIdConfiguration;
|
||||
const result = configValidationService.validateConfig(config);
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@ -84,7 +83,7 @@ describe('Config Validation Service', () => {
|
||||
} as OpenIdConfiguration;
|
||||
const result = configValidationService.validateConfig(config);
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@ -93,7 +92,7 @@ describe('Config Validation Service', () => {
|
||||
const config = { ...VALID_CONFIG, redirectUrl: '' };
|
||||
const result = configValidationService.validateConfig(config);
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@ -107,7 +106,7 @@ describe('Config Validation Service', () => {
|
||||
} as OpenIdConfiguration;
|
||||
const result = configValidationService.validateConfig(config);
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@ -120,12 +119,12 @@ describe('Config Validation Service', () => {
|
||||
scopes: 'scope1 scope2 but_no_offline_access',
|
||||
};
|
||||
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
const loggerWarningSpy = spyOn(loggerService, 'logWarning');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
|
||||
|
||||
const result = configValidationService.validateConfig(config);
|
||||
|
||||
expect(result).toBeTrue();
|
||||
expect(result).toBeTruthy();
|
||||
expect(loggerSpy).not.toHaveBeenCalled();
|
||||
expect(loggerWarningSpy).toHaveBeenCalled();
|
||||
});
|
||||
@ -146,47 +145,47 @@ describe('Config Validation Service', () => {
|
||||
scopes: 'scope1 scope2 but_no_offline_access',
|
||||
};
|
||||
|
||||
const loggerErrorSpy = spyOn(loggerService, 'logError');
|
||||
const loggerWarningSpy = spyOn(loggerService, 'logWarning');
|
||||
const loggerErrorSpy = vi.spyOn(loggerService, 'logError');
|
||||
const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
|
||||
|
||||
const result = configValidationService.validateConfigs([
|
||||
config1,
|
||||
config2,
|
||||
]);
|
||||
|
||||
expect(result).toBeTrue();
|
||||
expect(result).toBeTruthy();
|
||||
expect(loggerErrorSpy).not.toHaveBeenCalled();
|
||||
expect(loggerWarningSpy.calls.argsFor(0)).toEqual([
|
||||
expect(vi.mocked(loggerWarningSpy).mock.calls[0]).toEqual([
|
||||
config1,
|
||||
'You added multiple configs with the same authority, clientId and scope',
|
||||
]);
|
||||
expect(loggerWarningSpy.calls.argsFor(1)).toEqual([
|
||||
expect(vi.mocked(loggerWarningSpy).mock.calls[1]).toEqual([
|
||||
config2,
|
||||
'You added multiple configs with the same authority, clientId and scope',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return false and a better error message when config is not passed as object with config property', () => {
|
||||
const loggerWarningSpy = spyOn(loggerService, 'logWarning');
|
||||
const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
|
||||
|
||||
const result = configValidationService.validateConfigs([]);
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
expect(loggerWarningSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateConfigs', () => {
|
||||
it('calls internal method with empty array if something falsy is passed', () => {
|
||||
const spy = spyOn(
|
||||
const spy = vi.spyOn(
|
||||
configValidationService as any,
|
||||
'validateConfigsInternal'
|
||||
).and.callThrough();
|
||||
);
|
||||
|
||||
const result = configValidationService.validateConfigs([]);
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(spy).toHaveBeenCalledOnceWith([], allMultipleConfigRules);
|
||||
expect(result).toBeFalsy();
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith([], allMultipleConfigRules);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { CryptoService } from '../utils/crypto/crypto.service';
|
||||
import {
|
||||
JwkExtractor,
|
||||
|
@ -1,14 +1,15 @@
|
||||
import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpErrorResponse, HttpHeaders } from '@ngify/http';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { createRetriableStream } from '../../../test/create-retriable-stream.helper';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { createRetriableStream } from '../../testing/create-retriable-stream.helper';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { TokenValidationService } from '../../validation/token-validation.service';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { CodeFlowCallbackHandlerService } from './code-flow-callback-handler.service';
|
||||
|
||||
@ -46,13 +47,16 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
});
|
||||
|
||||
describe('codeFlowCallback', () => {
|
||||
it('throws error if no state is given', waitForAsync(() => {
|
||||
const getUrlParameterSpy = spyOn(
|
||||
urlService,
|
||||
'getUrlParameter'
|
||||
).and.returnValue('params');
|
||||
it('throws error if no state is given', async () => {
|
||||
const getUrlParameterSpy = vi
|
||||
.spyOn(urlService, 'getUrlParameter')
|
||||
.mockReturnValue('params');
|
||||
|
||||
getUrlParameterSpy.withArgs('test-url', 'state').and.returnValue('');
|
||||
mockImplementationWhenArgsEqual(
|
||||
getUrlParameterSpy,
|
||||
['test-url', 'state'],
|
||||
() => ''
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
@ -61,15 +65,14 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws error if no code is given', waitForAsync(() => {
|
||||
const getUrlParameterSpy = spyOn(
|
||||
urlService,
|
||||
'getUrlParameter'
|
||||
).and.returnValue('params');
|
||||
it('throws error if no code is given', async () => {
|
||||
const getUrlParameterSpy = vi
|
||||
.spyOn(urlService, 'getUrlParameter')
|
||||
.mockReturnValue('params');
|
||||
|
||||
getUrlParameterSpy.withArgs('test-url', 'code').and.returnValue('');
|
||||
getUrlParameterSpy.withArgs('test-url', 'code').mockReturnValue('');
|
||||
|
||||
service
|
||||
.codeFlowCallback('test-url', { configId: 'configId1' })
|
||||
@ -78,10 +81,10 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns callbackContext if all params are good', waitForAsync(() => {
|
||||
spyOn(urlService, 'getUrlParameter').and.returnValue('params');
|
||||
it('returns callbackContext if all params are good', async () => {
|
||||
vi.spyOn(urlService, 'getUrlParameter').mockReturnValue('params');
|
||||
|
||||
const expectedCallbackContext = {
|
||||
code: 'params',
|
||||
@ -100,7 +103,7 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
.subscribe((callbackContext) => {
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('codeFlowCodeRequest ', () => {
|
||||
@ -112,11 +115,11 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
url: 'https://identity-server.test/openid-connect/token',
|
||||
});
|
||||
|
||||
it('throws error if state is not correct', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('throws error if state is not correct', async () => {
|
||||
vi.spyOn(
|
||||
tokenValidationService,
|
||||
'validateStateFromHashCallback'
|
||||
).and.returnValue(false);
|
||||
).mockReturnValue(false);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
@ -125,16 +128,18 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws error if authWellknownEndpoints is null is given', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('throws error if authWellknownEndpoints is null is given', async () => {
|
||||
vi.spyOn(
|
||||
tokenValidationService,
|
||||
'validateStateFromHashCallback'
|
||||
).and.returnValue(true);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue(null);
|
||||
).mockReturnValue(true);
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => null
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
@ -143,16 +148,18 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws error if tokenendpoint is null is given', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('throws error if tokenendpoint is null is given', async () => {
|
||||
vi.spyOn(
|
||||
tokenValidationService,
|
||||
'validateStateFromHashCallback'
|
||||
).and.returnValue(true);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ tokenEndpoint: null });
|
||||
).mockReturnValue(true);
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ tokenEndpoint: null })
|
||||
);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
@ -161,34 +168,36 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls dataService if all params are good', waitForAsync(() => {
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
|
||||
it('calls dataService if all params are good', async () => {
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
tokenValidationService,
|
||||
'validateStateFromHashCallback'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
|
||||
.subscribe(() => {
|
||||
expect(postSpy).toHaveBeenCalledOnceWith(
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
jasmine.any(HttpHeaders)
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls url service with custom token params', waitForAsync(() => {
|
||||
const urlServiceSpy = spyOn(
|
||||
it('calls url service with custom token params', async () => {
|
||||
const urlServiceSpy = vi.spyOn(
|
||||
urlService,
|
||||
'createBodyForCodeFlowCodeRequest'
|
||||
);
|
||||
@ -197,76 +206,84 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
customParamsCodeRequest: { foo: 'bar' },
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
tokenValidationService,
|
||||
'validateStateFromHashCallback'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config)
|
||||
.subscribe(() => {
|
||||
expect(urlServiceSpy).toHaveBeenCalledOnceWith('foo', config, {
|
||||
expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, {
|
||||
foo: 'bar',
|
||||
});
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls dataService with correct headers if all params are good', waitForAsync(() => {
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
|
||||
it('calls dataService with correct headers if all params are good', async () => {
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
customParamsCodeRequest: { foo: 'bar' },
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
tokenValidationService,
|
||||
'validateStateFromHashCallback'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
|
||||
service
|
||||
.codeFlowCodeRequest({} as CallbackContext, config)
|
||||
.subscribe(() => {
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
|
||||
|
||||
expect(httpHeaders.has('Content-Type')).toBeTrue();
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns error in case of http error', waitForAsync(() => {
|
||||
spyOn(dataService, 'post').and.returnValue(throwError(() => HTTP_ERROR));
|
||||
it('returns error in case of http error', async () => {
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
throwError(() => HTTP_ERROR)
|
||||
);
|
||||
const config = {
|
||||
configId: 'configId1',
|
||||
customParamsCodeRequest: { foo: 'bar' },
|
||||
authority: 'authority',
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
|
||||
error: (err) => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and succeeds', waitForAsync(() => {
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(
|
||||
it('retries request in case of no connection http error and succeeds', async () => {
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => CONNECTION_ERROR),
|
||||
of({})
|
||||
@ -278,14 +295,16 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
authority: 'authority',
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
tokenValidationService,
|
||||
'validateStateFromHashCallback'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
|
||||
next: (res) => {
|
||||
@ -297,10 +316,10 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and fails because of http error afterwards', waitForAsync(() => {
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(
|
||||
it('retries request in case of no connection http error and fails because of http error afterwards', async () => {
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => CONNECTION_ERROR),
|
||||
throwError(() => HTTP_ERROR)
|
||||
@ -312,14 +331,16 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
authority: 'authority',
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
tokenValidationService,
|
||||
'validateStateFromHashCallback'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
|
||||
service.codeFlowCodeRequest({} as CallbackContext, config).subscribe({
|
||||
next: (res) => {
|
||||
@ -331,6 +352,6 @@ describe('CodeFlowCallbackHandlerService', () => {
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { HttpErrorResponse } from '@ngify/http';
|
||||
import { isNetworkError } from './error-helper';
|
||||
|
||||
describe('error helper', () => {
|
||||
@ -27,31 +27,31 @@ describe('error helper', () => {
|
||||
});
|
||||
|
||||
it('returns true on http error with status = 0', () => {
|
||||
expect(isNetworkError(CONNECTION_ERROR)).toBeTrue();
|
||||
expect(isNetworkError(CONNECTION_ERROR)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns true on http error with status = 0 and unknown error', () => {
|
||||
expect(isNetworkError(UNKNOWN_CONNECTION_ERROR)).toBeTrue();
|
||||
expect(isNetworkError(UNKNOWN_CONNECTION_ERROR)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns true on http error with status <> 0 and error ProgressEvent', () => {
|
||||
expect(isNetworkError(PARTIAL_CONNECTION_ERROR)).toBeTrue();
|
||||
expect(isNetworkError(PARTIAL_CONNECTION_ERROR)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns false on non http error', () => {
|
||||
expect(isNetworkError(new Error('not a HttpErrorResponse'))).toBeFalse();
|
||||
expect(isNetworkError(new Error('not a HttpErrorResponse'))).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false on string error', () => {
|
||||
expect(isNetworkError('not a HttpErrorResponse')).toBeFalse();
|
||||
expect(isNetworkError('not a HttpErrorResponse')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false on undefined', () => {
|
||||
expect(isNetworkError(undefined)).toBeFalse();
|
||||
expect(isNetworkError(undefined)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false on empty http error', () => {
|
||||
expect(isNetworkError(HTTP_ERROR)).toBeFalse();
|
||||
expect(isNetworkError(HTTP_ERROR)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { JwtKey, JwtKeys } from '../../validation/jwtkeys';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import type { JwtKey, JwtKeys } from '../../validation/jwtkeys';
|
||||
import { ValidationResult } from '../../validation/validation-result';
|
||||
import { AuthResult, CallbackContext } from '../callback-context';
|
||||
import type { AuthResult, CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { ResetAuthDataService } from '../reset-auth-data.service';
|
||||
import { SigninKeyDataService } from '../signin-key-data.service';
|
||||
@ -46,9 +47,6 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
mockProvider(ResetAuthDataService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(HistoryJwtKeysCallbackHandlerService);
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
resetAuthDataService = TestBed.inject(ResetAuthDataService);
|
||||
@ -62,8 +60,8 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
});
|
||||
|
||||
describe('callbackHistoryAndResetJwtKeys', () => {
|
||||
it('writes authResult into the storage', waitForAsync(() => {
|
||||
const storagePersistenceServiceSpy = spyOn(
|
||||
it('writes authResult into the storage', async () => {
|
||||
const storagePersistenceServiceSpy = vi.spyOn(
|
||||
storagePersistenceService,
|
||||
'write'
|
||||
);
|
||||
@ -75,86 +73,86 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
const callbackContext = {
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe(() => {
|
||||
expect(storagePersistenceServiceSpy.calls.allArgs()).toEqual([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allconfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allconfigs[0]],
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);
|
||||
// write authnResult & jwtKeys
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('writes refresh_token into the storage without reuse (refresh token rotation)', waitForAsync(() => {
|
||||
it('writes refresh_token into the storage without reuse (refresh token rotation)', async () => {
|
||||
const DUMMY_AUTH_RESULT = {
|
||||
refresh_token: 'dummy_refresh_token',
|
||||
id_token: 'some-id-token',
|
||||
};
|
||||
|
||||
const storagePersistenceServiceSpy = spyOn(
|
||||
const storagePersistenceServiceSpy = vi.spyOn(
|
||||
storagePersistenceService,
|
||||
'write'
|
||||
);
|
||||
const callbackContext = {
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe(() => {
|
||||
expect(storagePersistenceServiceSpy.calls.allArgs()).toEqual([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allconfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allconfigs[0]],
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);
|
||||
// write authnResult & refresh_token & jwtKeys
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('writes refresh_token into the storage with reuse (without refresh token rotation)', waitForAsync(() => {
|
||||
it('writes refresh_token into the storage with reuse (without refresh token rotation)', async () => {
|
||||
const DUMMY_AUTH_RESULT = {
|
||||
refresh_token: 'dummy_refresh_token',
|
||||
id_token: 'some-id-token',
|
||||
};
|
||||
|
||||
const storagePersistenceServiceSpy = spyOn(
|
||||
const storagePersistenceServiceSpy = vi.spyOn(
|
||||
storagePersistenceService,
|
||||
'write'
|
||||
);
|
||||
const callbackContext = {
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
@ -162,27 +160,27 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe(() => {
|
||||
expect(storagePersistenceServiceSpy.calls.allArgs()).toEqual([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allconfigs[0]],
|
||||
['reusable_refresh_token', 'dummy_refresh_token', allconfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allconfigs[0]],
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['reusable_refresh_token', 'dummy_refresh_token', allConfigs[0]],
|
||||
['jwtKeys', { keys: [] }, allConfigs[0]],
|
||||
]);
|
||||
// write authnResult & refresh_token & jwtKeys
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('resetBrowserHistory if historyCleanup is turned on and is not in a renewProcess', waitForAsync(() => {
|
||||
it('resetBrowserHistory if historyCleanup is turned on and is not in a renewProcess', async () => {
|
||||
const DUMMY_AUTH_RESULT = {
|
||||
id_token: 'some-id-token',
|
||||
};
|
||||
@ -190,30 +188,30 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
isRenewProcess: false,
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: false,
|
||||
},
|
||||
];
|
||||
|
||||
const windowSpy = spyOn(window.history, 'replaceState');
|
||||
const windowSpy = vi.spyOn(window.history, 'replaceState');
|
||||
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [] } as JwtKeys)
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe(() => {
|
||||
expect(windowSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns callbackContext with jwtkeys filled if everything works fine', waitForAsync(() => {
|
||||
it('returns callbackContext with jwtkeys filled if everything works fine', async () => {
|
||||
const DUMMY_AUTH_RESULT = {
|
||||
id_token: 'some-id-token',
|
||||
};
|
||||
@ -222,21 +220,21 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
isRenewProcess: false,
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: false,
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({ keys: [{ kty: 'henlo' } as JwtKey] } as JwtKeys)
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe((result) => {
|
||||
expect(result).toEqual({
|
||||
@ -245,9 +243,9 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
jwtKeys: { keys: [{ kty: 'henlo' }] },
|
||||
} as CallbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns error if no jwtKeys have been in the call --> keys are null', waitForAsync(() => {
|
||||
it('returns error if no jwtKeys have been in the call --> keys are null', async () => {
|
||||
const DUMMY_AUTH_RESULT = {
|
||||
id_token: 'some-id-token',
|
||||
};
|
||||
@ -256,32 +254,32 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
isRenewProcess: false,
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: false,
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of({} as JwtKeys)
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual(
|
||||
`Failed to retrieve signing key with error: Error: Failed to retrieve signing key`
|
||||
'Failed to retrieve signing key with error: Error: Failed to retrieve signing key'
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns error if no jwtKeys have been in the call --> keys throw an error', waitForAsync(() => {
|
||||
it('returns error if no jwtKeys have been in the call --> keys throw an error', async () => {
|
||||
const DUMMY_AUTH_RESULT = {
|
||||
id_token: 'some-id-token',
|
||||
};
|
||||
@ -289,36 +287,36 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
isRenewProcess: false,
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: false,
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
throwError(() => new Error('error'))
|
||||
);
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual(
|
||||
`Failed to retrieve signing key with error: Error: Error: error`
|
||||
'Failed to retrieve signing key with error: Error: Error: error'
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns error if callbackContext.authresult has an error property filled', waitForAsync(() => {
|
||||
it('returns error if callbackContext.authresult has an error property filled', async () => {
|
||||
const callbackContext = {
|
||||
authResult: { error: 'someError' },
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
@ -328,36 +326,36 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual(
|
||||
`AuthCallback AuthResult came with error: someError`
|
||||
'AuthCallback AuthResult came with error: someError'
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls resetAuthorizationData, resets nonce and authStateService in case of an error', waitForAsync(() => {
|
||||
it('calls resetAuthorizationData, resets nonce and authStateService in case of an error', async () => {
|
||||
const callbackContext = {
|
||||
authResult: { error: 'someError' },
|
||||
isRenewProcess: false,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
},
|
||||
];
|
||||
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
const setNonceSpy = spyOn(flowsDataService, 'setNonce');
|
||||
const updateAndPublishAuthStateSpy = spyOn(
|
||||
const setNonceSpy = vi.spyOn(flowsDataService, 'setNonce');
|
||||
const updateAndPublishAuthStateSpy = vi.spyOn(
|
||||
authStateService,
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
@ -365,40 +363,42 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.SecureTokenServerError,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls authStateService.updateAndPublishAuthState with login required if the error is `login_required`', waitForAsync(() => {
|
||||
it('calls authStateService.updateAndPublishAuthState with login required if the error is `login_required`', async () => {
|
||||
const callbackContext = {
|
||||
authResult: { error: 'login_required' },
|
||||
isRenewProcess: false,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
},
|
||||
];
|
||||
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
const setNonceSpy = spyOn(flowsDataService, 'setNonce');
|
||||
const updateAndPublishAuthStateSpy = spyOn(
|
||||
const setNonceSpy = vi.spyOn(flowsDataService, 'setNonce');
|
||||
const updateAndPublishAuthStateSpy = vi.spyOn(
|
||||
authStateService,
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
@ -406,23 +406,25 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
callbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(setNonceSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should store jwtKeys', waitForAsync(() => {
|
||||
it('should store jwtKeys', async () => {
|
||||
const DUMMY_AUTH_RESULT = {
|
||||
id_token: 'some-id-token',
|
||||
};
|
||||
@ -430,33 +432,33 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
const initialCallbackContext = {
|
||||
authResult: DUMMY_AUTH_RESULT,
|
||||
} as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
},
|
||||
];
|
||||
const storagePersistenceServiceSpy = spyOn(
|
||||
const storagePersistenceServiceSpy = vi.spyOn(
|
||||
storagePersistenceService,
|
||||
'write'
|
||||
);
|
||||
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
of(DUMMY_JWT_KEYS)
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledTimes(2);
|
||||
expect(storagePersistenceServiceSpy.calls.allArgs()).toEqual([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allconfigs[0]],
|
||||
['jwtKeys', DUMMY_JWT_KEYS, allconfigs[0]],
|
||||
expect(storagePersistenceServiceSpy).toBeCalledWith([
|
||||
['authnResult', DUMMY_AUTH_RESULT, allConfigs[0]],
|
||||
['jwtKeys', DUMMY_JWT_KEYS, allConfigs[0]],
|
||||
]);
|
||||
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
@ -465,9 +467,9 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not store jwtKeys on error', waitForAsync(() => {
|
||||
it('should not store jwtKeys on error', async () => {
|
||||
const authResult = {
|
||||
id_token: 'some-id-token',
|
||||
access_token: 'some-access-token',
|
||||
@ -476,26 +478,26 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
authResult,
|
||||
} as CallbackContext;
|
||||
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
},
|
||||
];
|
||||
const storagePersistenceServiceSpy = spyOn(
|
||||
const storagePersistenceServiceSpy = vi.spyOn(
|
||||
storagePersistenceService,
|
||||
'write'
|
||||
);
|
||||
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
@ -505,16 +507,18 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
|
||||
// storagePersistenceService.write() should not have been called with jwtKeys
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledOnceWith(
|
||||
expect(
|
||||
storagePersistenceServiceSpy
|
||||
).toHaveBeenCalledExactlyOnceWith(
|
||||
'authnResult',
|
||||
authResult,
|
||||
allconfigs[0]
|
||||
allConfigs[0]
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should fallback to stored jwtKeys on error', waitForAsync(() => {
|
||||
it('should fallback to stored jwtKeys on error', async () => {
|
||||
const authResult = {
|
||||
id_token: 'some-id-token',
|
||||
access_token: 'some-access-token',
|
||||
@ -523,66 +527,65 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
authResult,
|
||||
} as CallbackContext;
|
||||
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
},
|
||||
];
|
||||
const storagePersistenceServiceSpy = spyOn(
|
||||
const storagePersistenceServiceSpy = vi.spyOn(
|
||||
storagePersistenceService,
|
||||
'read'
|
||||
);
|
||||
|
||||
storagePersistenceServiceSpy.and.returnValue(DUMMY_JWT_KEYS);
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
storagePersistenceServiceSpy.mockReturnValue(DUMMY_JWT_KEYS);
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledOnceWith(
|
||||
'jwtKeys',
|
||||
allconfigs[0]
|
||||
);
|
||||
expect(
|
||||
storagePersistenceServiceSpy
|
||||
).toHaveBeenCalledExactlyOnceWith('jwtKeys', allConfigs[0]);
|
||||
expect(callbackContext.jwtKeys).toEqual(DUMMY_JWT_KEYS);
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should throw error if no jwtKeys are stored', waitForAsync(() => {
|
||||
it('should throw error if no jwtKeys are stored', async () => {
|
||||
const authResult = {
|
||||
id_token: 'some-id-token',
|
||||
access_token: 'some-access-token',
|
||||
} as AuthResult;
|
||||
|
||||
const initialCallbackContext = { authResult } as CallbackContext;
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
historyCleanupOff: true,
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(storagePersistenceService, 'read').and.returnValue(null);
|
||||
spyOn(signInKeyDataService, 'getSigningKeys').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'read').mockReturnValue(null);
|
||||
vi.spyOn(signInKeyDataService, 'getSigningKeys').mockReturnValue(
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
service
|
||||
.callbackHistoryAndResetJwtKeys(
|
||||
initialCallbackContext,
|
||||
allconfigs[0],
|
||||
allconfigs
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
next: (callbackContext: CallbackContext) => {
|
||||
@ -592,7 +595,7 @@ describe('HistoryJwtKeysCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('historyCleanUpTurnedOn ', () => {
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, switchMap, tap } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { JwtKeys } from '../../validation/jwtkeys';
|
||||
import type { JwtKeys } from '../../validation/jwtkeys';
|
||||
import { ValidationResult } from '../../validation/validation-result';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { ResetAuthDataService } from '../reset-auth-data.service';
|
||||
import { SigninKeyDataService } from '../signin-key-data.service';
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { ResetAuthDataService } from '../reset-auth-data.service';
|
||||
import { ImplicitFlowCallbackHandlerService } from './implicit-flow-callback-handler.service';
|
||||
@ -34,9 +35,6 @@ describe('ImplicitFlowCallbackHandlerService', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.inject(ImplicitFlowCallbackHandlerService);
|
||||
flowsDataService = TestBed.inject(FlowsDataService);
|
||||
resetAuthDataService = TestBed.inject(ResetAuthDataService);
|
||||
@ -47,46 +45,46 @@ describe('ImplicitFlowCallbackHandlerService', () => {
|
||||
});
|
||||
|
||||
describe('implicitFlowCallback', () => {
|
||||
it('calls "resetAuthorizationData" if silent renew is not running', waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(false);
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
it('calls "resetAuthorizationData" if silent renew is not running', async () => {
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(false);
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
},
|
||||
];
|
||||
|
||||
service
|
||||
.implicitFlowCallback(allconfigs[0], allconfigs, 'any-hash')
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
|
||||
.subscribe(() => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('does NOT calls "resetAuthorizationData" if silent renew is running', waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
it('does NOT calls "resetAuthorizationData" if silent renew is running', async () => {
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
},
|
||||
];
|
||||
|
||||
service
|
||||
.implicitFlowCallback(allconfigs[0], allconfigs, 'any-hash')
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
|
||||
.subscribe(() => {
|
||||
expect(resetAuthorizationDataSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns callbackContext if all params are good', waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
|
||||
it('returns callbackContext if all params are good', async () => {
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
|
||||
const expectedCallbackContext = {
|
||||
code: '',
|
||||
refreshToken: '',
|
||||
@ -99,21 +97,21 @@ describe('ImplicitFlowCallbackHandlerService', () => {
|
||||
existingIdToken: null,
|
||||
} as CallbackContext;
|
||||
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
},
|
||||
];
|
||||
|
||||
service
|
||||
.implicitFlowCallback(allconfigs[0], allconfigs, 'anyHash')
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs, 'anyHash')
|
||||
.subscribe((callbackContext) => {
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('uses window location hash if no hash is passed', waitForAsync(() => {
|
||||
spyOn(flowsDataService, 'isSilentRenewRunning').and.returnValue(true);
|
||||
it('uses window location hash if no hash is passed', async () => {
|
||||
vi.spyOn(flowsDataService, 'isSilentRenewRunning').mockReturnValue(true);
|
||||
const expectedCallbackContext = {
|
||||
code: '',
|
||||
refreshToken: '',
|
||||
@ -126,17 +124,17 @@ describe('ImplicitFlowCallbackHandlerService', () => {
|
||||
existingIdToken: null,
|
||||
} as CallbackContext;
|
||||
|
||||
const allconfigs = [
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
},
|
||||
];
|
||||
|
||||
service
|
||||
.implicitFlowCallback(allconfigs[0], allconfigs)
|
||||
.implicitFlowCallback(allConfigs[0]!, allConfigs)
|
||||
.subscribe((callbackContext) => {
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of } from 'rxjs';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { AuthResult, CallbackContext } from '../callback-context';
|
||||
import type { AuthResult, CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { ResetAuthDataService } from '../reset-auth-data.service';
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { RefreshSessionCallbackHandlerService } from './refresh-session-callback-handler.service';
|
||||
|
||||
@ -33,15 +34,15 @@ describe('RefreshSessionCallbackHandlerService', () => {
|
||||
});
|
||||
|
||||
describe('refreshSessionWithRefreshTokens', () => {
|
||||
it('returns callbackContext if all params are good', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('returns callbackContext if all params are good', async () => {
|
||||
vi.spyOn(
|
||||
flowsDataService,
|
||||
'getExistingOrCreateAuthStateControl'
|
||||
).and.returnValue('state-data');
|
||||
spyOn(authStateService, 'getRefreshToken').and.returnValue(
|
||||
).mockReturnValue('state-data');
|
||||
vi.spyOn(authStateService, 'getRefreshToken').mockReturnValue(
|
||||
'henlo-furiend'
|
||||
);
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('henlo-legger');
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('henlo-legger');
|
||||
|
||||
const expectedCallbackContext = {
|
||||
code: '',
|
||||
@ -60,15 +61,15 @@ describe('RefreshSessionCallbackHandlerService', () => {
|
||||
.subscribe((callbackContext) => {
|
||||
expect(callbackContext).toEqual(expectedCallbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws error if no refresh token is given', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('throws error if no refresh token is given', async () => {
|
||||
vi.spyOn(
|
||||
flowsDataService,
|
||||
'getExistingOrCreateAuthStateControl'
|
||||
).and.returnValue('state-data');
|
||||
spyOn(authStateService, 'getRefreshToken').and.returnValue('');
|
||||
spyOn(authStateService, 'getIdToken').and.returnValue('henlo-legger');
|
||||
).mockReturnValue('state-data');
|
||||
vi.spyOn(authStateService, 'getRefreshToken').mockReturnValue('');
|
||||
vi.spyOn(authStateService, 'getIdToken').mockReturnValue('henlo-legger');
|
||||
|
||||
service
|
||||
.refreshSessionWithRefreshTokens({ configId: 'configId1' })
|
||||
@ -77,6 +78,6 @@ describe('RefreshSessionCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpErrorResponse, HttpHeaders } from '@ngify/http';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { createRetriableStream } from '../../../test/create-retriable-stream.helper';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { createRetriableStream } from '../../testing/create-retriable-stream.helper';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { RefreshTokenCallbackHandlerService } from './refresh-token-callback-handler.service';
|
||||
|
||||
describe('RefreshTokenCallbackHandlerService', () => {
|
||||
@ -46,7 +47,7 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
url: 'https://identity-server.test/openid-connect/token',
|
||||
});
|
||||
|
||||
it('throws error if no tokenEndpoint is given', waitForAsync(() => {
|
||||
it('throws error if no tokenEndpoint is given', async () => {
|
||||
(service as any)
|
||||
.refreshTokensRequestTokens({} as CallbackContext)
|
||||
.subscribe({
|
||||
@ -54,41 +55,45 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls data service if all params are good', waitForAsync(() => {
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
|
||||
it('calls data service if all params are good', async () => {
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
configId: 'configId1',
|
||||
})
|
||||
.subscribe(() => {
|
||||
expect(postSpy).toHaveBeenCalledOnceWith(
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'tokenEndpoint',
|
||||
undefined,
|
||||
{ configId: 'configId1' },
|
||||
jasmine.any(HttpHeaders)
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
|
||||
|
||||
expect(httpHeaders.has('Content-Type')).toBeTrue();
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls data service with correct headers if all params are good', waitForAsync(() => {
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(of({}));
|
||||
it('calls data service with correct headers if all params are good', async () => {
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, {
|
||||
@ -97,20 +102,24 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
.subscribe(() => {
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
|
||||
|
||||
expect(httpHeaders.has('Content-Type')).toBeTrue();
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns error in case of http error', waitForAsync(() => {
|
||||
spyOn(dataService, 'post').and.returnValue(throwError(() => HTTP_ERROR));
|
||||
it('returns error in case of http error', async () => {
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
throwError(() => HTTP_ERROR)
|
||||
);
|
||||
const config = { configId: 'configId1', authority: 'authority' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
@ -119,10 +128,10 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and succeeds', waitForAsync(() => {
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(
|
||||
it('retries request in case of no connection http error and succeeds', async () => {
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => CONNECTION_ERROR),
|
||||
of({})
|
||||
@ -130,9 +139,11 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
);
|
||||
const config = { configId: 'configId1', authority: 'authority' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
@ -146,10 +157,10 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
expect(err).toBeFalsy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('retries request in case of no connection http error and fails because of http error afterwards', waitForAsync(() => {
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(
|
||||
it('retries request in case of no connection http error and fails because of http error afterwards', async () => {
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => CONNECTION_ERROR),
|
||||
throwError(() => HTTP_ERROR)
|
||||
@ -157,9 +168,11 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
);
|
||||
const config = { configId: 'configId1', authority: 'authority' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ tokenEndpoint: 'tokenEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ tokenEndpoint: 'tokenEndpoint' })
|
||||
);
|
||||
|
||||
service
|
||||
.refreshTokensRequestTokens({} as CallbackContext, config)
|
||||
@ -173,6 +186,6 @@ describe('RefreshTokenCallbackHandlerService', () => {
|
||||
expect(postSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StateValidationResult } from '../../validation/state-validation-result';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import type { StateValidationResult } from '../../validation/state-validation-result';
|
||||
import { StateValidationService } from '../../validation/state-validation.service';
|
||||
import { ValidationResult } from '../../validation/validation-result';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { ResetAuthDataService } from '../reset-auth-data.service';
|
||||
import { StateValidationCallbackHandlerService } from './state-validation-callback-handler.service';
|
||||
|
||||
@ -56,8 +57,11 @@ describe('StateValidationCallbackHandlerService', () => {
|
||||
});
|
||||
|
||||
describe('callbackStateValidation', () => {
|
||||
it('returns callbackContext with validationResult if validationResult is valid', waitForAsync(() => {
|
||||
spyOn(stateValidationService, 'getValidatedStateResult').and.returnValue(
|
||||
it('returns callbackContext with validationResult if validationResult is valid', async () => {
|
||||
vi.spyOn(
|
||||
stateValidationService,
|
||||
'getValidatedStateResult'
|
||||
).mockReturnValue(
|
||||
of({
|
||||
idToken: 'idTokenJustForTesting',
|
||||
authResponseIsValid: true,
|
||||
@ -68,7 +72,7 @@ describe('StateValidationCallbackHandlerService', () => {
|
||||
service
|
||||
.callbackStateValidation(
|
||||
{} as CallbackContext,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe((newCallbackContext) => {
|
||||
@ -79,47 +83,53 @@ describe('StateValidationCallbackHandlerService', () => {
|
||||
},
|
||||
} as CallbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('logs error in case of an error', waitForAsync(() => {
|
||||
spyOn(stateValidationService, 'getValidatedStateResult').and.returnValue(
|
||||
it('logs error in case of an error', async () => {
|
||||
vi.spyOn(
|
||||
stateValidationService,
|
||||
'getValidatedStateResult'
|
||||
).mockReturnValue(
|
||||
of({
|
||||
authResponseIsValid: false,
|
||||
} as StateValidationResult)
|
||||
);
|
||||
|
||||
const loggerSpy = spyOn(loggerService, 'logWarning');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logWarning');
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
service
|
||||
.callbackStateValidation(
|
||||
{} as CallbackContext,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(loggerSpy).toHaveBeenCalledOnceWith(
|
||||
allConfigs[0],
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
'authorizedCallback, token(s) validation failed, resetting. Hash: &anyFakeHash'
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls resetAuthDataService.resetAuthorizationData and authStateService.updateAndPublishAuthState in case of an error', waitForAsync(() => {
|
||||
spyOn(stateValidationService, 'getValidatedStateResult').and.returnValue(
|
||||
it('calls resetAuthDataService.resetAuthorizationData and authStateService.updateAndPublishAuthState in case of an error', async () => {
|
||||
vi.spyOn(
|
||||
stateValidationService,
|
||||
'getValidatedStateResult'
|
||||
).mockReturnValue(
|
||||
of({
|
||||
authResponseIsValid: false,
|
||||
state: ValidationResult.LoginRequired,
|
||||
} as StateValidationResult)
|
||||
);
|
||||
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
const updateAndPublishAuthStateSpy = spyOn(
|
||||
const updateAndPublishAuthStateSpy = vi.spyOn(
|
||||
authStateService,
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
@ -128,19 +138,21 @@ describe('StateValidationCallbackHandlerService', () => {
|
||||
service
|
||||
.callbackStateValidation(
|
||||
{ isRenewProcess: true } as CallbackContext,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: true,
|
||||
});
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StateValidationResult } from '../../validation/state-validation-result';
|
||||
import type { StateValidationResult } from '../../validation/state-validation-result';
|
||||
import { StateValidationService } from '../../validation/state-validation.service';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { ResetAuthDataService } from '../reset-auth-data.service';
|
||||
|
||||
@Injectable()
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { UserService } from '../../user-data/user.service';
|
||||
import { StateValidationResult } from '../../validation/state-validation-result';
|
||||
import { ValidationResult } from '../../validation/validation-result';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { ResetAuthDataService } from '../reset-auth-data.service';
|
||||
import { UserCallbackHandlerService } from './user-callback-handler.service';
|
||||
@ -44,7 +45,7 @@ describe('UserCallbackHandlerService', () => {
|
||||
});
|
||||
|
||||
describe('callbackUser', () => {
|
||||
it('calls flowsDataService.setSessionState with correct params if autoUserInfo is false, isRenewProcess is false and refreshToken is null', waitForAsync(() => {
|
||||
it('calls flowsDataService.setSessionState with correct params if autoUserInfo is false, isRenewProcess is false and refreshToken is null', async () => {
|
||||
const svr = new StateValidationResult(
|
||||
'accesstoken',
|
||||
'idtoken',
|
||||
@ -70,17 +71,17 @@ describe('UserCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
const spy = spyOn(flowsDataService, 'setSessionState');
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe((resultCallbackContext) => {
|
||||
expect(spy).toHaveBeenCalledOnceWith('mystate', allConfigs[0]);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('mystate', allConfigs[0]);
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false, isRenewProcess is true and refreshToken is null', waitForAsync(() => {
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false, isRenewProcess is true and refreshToken is null', async () => {
|
||||
const svr = new StateValidationResult(
|
||||
'accesstoken',
|
||||
'idtoken',
|
||||
@ -104,17 +105,17 @@ describe('UserCallbackHandlerService', () => {
|
||||
autoUserInfo: false,
|
||||
},
|
||||
];
|
||||
const spy = spyOn(flowsDataService, 'setSessionState');
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe((resultCallbackContext) => {
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value', waitForAsync(() => {
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value', async () => {
|
||||
const svr = new StateValidationResult(
|
||||
'accesstoken',
|
||||
'idtoken',
|
||||
@ -138,17 +139,17 @@ describe('UserCallbackHandlerService', () => {
|
||||
autoUserInfo: false,
|
||||
},
|
||||
];
|
||||
const spy = spyOn(flowsDataService, 'setSessionState');
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe((resultCallbackContext) => {
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('does NOT call flowsDataService.setSessionState if autoUserInfo is false isRenewProcess is false, refreshToken has value, id_token is false', waitForAsync(() => {
|
||||
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 callbackContext = {
|
||||
code: '',
|
||||
@ -168,17 +169,17 @@ describe('UserCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
const spy = spyOn(flowsDataService, 'setSessionState');
|
||||
const spy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe((resultCallbackContext) => {
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is false', waitForAsync(() => {
|
||||
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is false', async () => {
|
||||
const svr = new StateValidationResult(
|
||||
'accesstoken',
|
||||
'idtoken',
|
||||
@ -204,24 +205,24 @@ describe('UserCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
const updateAndPublishAuthStateSpy = spyOn(
|
||||
const updateAndPublishAuthStateSpy = vi.spyOn(
|
||||
authStateService,
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe((resultCallbackContext) => {
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.NotSet,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls userService.getAndPersistUserDataInStore with correct params if autoUserInfo is true', waitForAsync(() => {
|
||||
it('calls userService.getAndPersistUserDataInStore with correct params if autoUserInfo is true', async () => {
|
||||
const svr = new StateValidationResult(
|
||||
'accesstoken',
|
||||
'idtoken',
|
||||
@ -247,16 +248,17 @@ describe('UserCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
const getAndPersistUserDataInStoreSpy = spyOn(
|
||||
userService,
|
||||
'getAndPersistUserDataInStore'
|
||||
).and.returnValue(of({ user: 'some_data' }));
|
||||
const getAndPersistUserDataInStoreSpy = vi
|
||||
.spyOn(userService, 'getAndPersistUserDataInStore')
|
||||
.mockReturnValue(of({ user: 'some_data' }));
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe((resultCallbackContext) => {
|
||||
expect(getAndPersistUserDataInStoreSpy).toHaveBeenCalledOnceWith(
|
||||
allConfigs[0],
|
||||
expect(
|
||||
getAndPersistUserDataInStoreSpy
|
||||
).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
false,
|
||||
'idtoken',
|
||||
@ -264,9 +266,9 @@ describe('UserCallbackHandlerService', () => {
|
||||
);
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is true', waitForAsync(() => {
|
||||
it('calls authStateService.updateAndPublishAuthState with correct params if autoUserInfo is true', async () => {
|
||||
const svr = new StateValidationResult(
|
||||
'accesstoken',
|
||||
'idtoken',
|
||||
@ -293,27 +295,27 @@ describe('UserCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(userService, 'getAndPersistUserDataInStore').and.returnValue(
|
||||
vi.spyOn(userService, 'getAndPersistUserDataInStore').mockReturnValue(
|
||||
of({ user: 'some_data' })
|
||||
);
|
||||
const updateAndPublishAuthStateSpy = spyOn(
|
||||
const updateAndPublishAuthStateSpy = vi.spyOn(
|
||||
authStateService,
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe((resultCallbackContext) => {
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: true,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
});
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls flowsDataService.setSessionState with correct params if user data is present and NOT refresh token', waitForAsync(() => {
|
||||
it('calls flowsDataService.setSessionState with correct params if user data is present and NOT refresh token', async () => {
|
||||
const svr = new StateValidationResult(
|
||||
'accesstoken',
|
||||
'idtoken',
|
||||
@ -340,23 +342,23 @@ describe('UserCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(userService, 'getAndPersistUserDataInStore').and.returnValue(
|
||||
vi.spyOn(userService, 'getAndPersistUserDataInStore').mockReturnValue(
|
||||
of({ user: 'some_data' })
|
||||
);
|
||||
const setSessionStateSpy = spyOn(flowsDataService, 'setSessionState');
|
||||
const setSessionStateSpy = vi.spyOn(flowsDataService, 'setSessionState');
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe((resultCallbackContext) => {
|
||||
expect(setSessionStateSpy).toHaveBeenCalledOnceWith(
|
||||
expect(setSessionStateSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'mystate',
|
||||
allConfigs[0]
|
||||
);
|
||||
expect(resultCallbackContext).toEqual(callbackContext);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls authStateService.publishUnauthorizedState with correct params if user info which are coming back are null', waitForAsync(() => {
|
||||
it('calls authStateService.publishUnauthorizedState with correct params if user info which are coming back are null', async () => {
|
||||
const svr = new StateValidationResult(
|
||||
'accesstoken',
|
||||
'idtoken',
|
||||
@ -383,19 +385,21 @@ describe('UserCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(userService, 'getAndPersistUserDataInStore').and.returnValue(
|
||||
vi.spyOn(userService, 'getAndPersistUserDataInStore').mockReturnValue(
|
||||
of(null)
|
||||
);
|
||||
const updateAndPublishAuthStateSpy = spyOn(
|
||||
const updateAndPublishAuthStateSpy = vi.spyOn(
|
||||
authStateService,
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(updateAndPublishAuthStateSpy).toHaveBeenCalledOnceWith({
|
||||
expect(
|
||||
updateAndPublishAuthStateSpy
|
||||
).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.MaxOffsetExpired,
|
||||
isRenewProcess: false,
|
||||
@ -405,9 +409,9 @@ describe('UserCallbackHandlerService', () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls resetAuthDataService.resetAuthorizationData if user info which are coming back are null', waitForAsync(() => {
|
||||
it('calls resetAuthDataService.resetAuthorizationData if user info which are coming back are null', async () => {
|
||||
const svr = new StateValidationResult(
|
||||
'accesstoken',
|
||||
'idtoken',
|
||||
@ -434,16 +438,16 @@ describe('UserCallbackHandlerService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
spyOn(userService, 'getAndPersistUserDataInStore').and.returnValue(
|
||||
vi.spyOn(userService, 'getAndPersistUserDataInStore').mockReturnValue(
|
||||
of(null)
|
||||
);
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
|
||||
service
|
||||
.callbackUser(callbackContext, allConfigs[0], allConfigs)
|
||||
.callbackUser(callbackContext, allConfigs[0]!, allConfigs)
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(1);
|
||||
@ -452,6 +456,6 @@ describe('UserCallbackHandlerService', () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, switchMap } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { UserService } from '../../user-data/user.service';
|
||||
import { StateValidationResult } from '../../validation/state-validation-result';
|
||||
import { CallbackContext } from '../callback-context';
|
||||
import type { StateValidationResult } from '../../validation/state-validation-result';
|
||||
import type { CallbackContext } from '../callback-context';
|
||||
import { FlowsDataService } from '../flows-data.service';
|
||||
import { ResetAuthDataService } from '../reset-auth-data.service';
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { CryptoService } from '../utils/crypto/crypto.service';
|
||||
import { FlowsDataService } from './flows-data.service';
|
||||
import { RandomService } from './random/random.service';
|
||||
@ -37,12 +38,12 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('createNonce', () => {
|
||||
it('createNonce returns nonce and stores it', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'write');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
const result = service.createNonce({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(spy).toHaveBeenCalledOnceWith('authNonce', result, {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authNonce', result, {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
@ -50,32 +51,38 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('AuthStateControl', () => {
|
||||
it('getAuthStateControl returns property from store', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'read');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'read');
|
||||
|
||||
service.getAuthStateControl({ configId: 'configId1' });
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('authStateControl', {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authStateControl', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
|
||||
it('setAuthStateControl saves property in store', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'write');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
service.setAuthStateControl('ToSave', { configId: 'configId1' });
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('authStateControl', 'ToSave', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'authStateControl',
|
||||
'ToSave',
|
||||
{
|
||||
configId: 'configId1',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getExistingOrCreateAuthStateControl', () => {
|
||||
it('if nothing stored it creates a 40 char one and saves the authStateControl', () => {
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authStateControl', { configId: 'configId1' })
|
||||
.and.returnValue(null);
|
||||
const setSpy = spyOn(storagePersistenceService, 'write');
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authStateControl', { configId: 'configId1' }],
|
||||
() => null
|
||||
);
|
||||
const setSpy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
const result = service.getExistingOrCreateAuthStateControl({
|
||||
configId: 'configId1',
|
||||
@ -83,16 +90,22 @@ describe('Flows Data Service', () => {
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(result.length).toBe(41);
|
||||
expect(setSpy).toHaveBeenCalledOnceWith('authStateControl', result, {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(setSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'authStateControl',
|
||||
result,
|
||||
{
|
||||
configId: 'configId1',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('if stored it returns the value and does NOT Store the value again', () => {
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authStateControl', { configId: 'configId1' })
|
||||
.and.returnValue('someAuthStateControl');
|
||||
const setSpy = spyOn(storagePersistenceService, 'write');
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authStateControl', { configId: 'configId1' }],
|
||||
() => 'someAuthStateControl'
|
||||
);
|
||||
const setSpy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
const result = service.getExistingOrCreateAuthStateControl({
|
||||
configId: 'configId1',
|
||||
@ -106,11 +119,11 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('setSessionState', () => {
|
||||
it('setSessionState saves the value in the storage', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'write');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
service.setSessionState('Genesis', { configId: 'configId1' });
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('session_state', 'Genesis', {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('session_state', 'Genesis', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
@ -118,7 +131,7 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('resetStorageFlowData', () => {
|
||||
it('resetStorageFlowData calls correct method on storagePersistenceService', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'resetStorageFlowData');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'resetStorageFlowData');
|
||||
|
||||
service.resetStorageFlowData({ configId: 'configId1' });
|
||||
|
||||
@ -128,26 +141,27 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('codeVerifier', () => {
|
||||
it('getCodeVerifier returns value from the store', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'read')
|
||||
const spy = vi
|
||||
.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('codeVerifier', { configId: 'configId1' })
|
||||
.and.returnValue('Genesis');
|
||||
.mockReturnValue('Genesis');
|
||||
|
||||
const result = service.getCodeVerifier({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBe('Genesis');
|
||||
expect(spy).toHaveBeenCalledOnceWith('codeVerifier', {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('codeVerifier', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
|
||||
it('createCodeVerifier returns random createCodeVerifier and stores it', () => {
|
||||
const setSpy = spyOn(storagePersistenceService, 'write');
|
||||
const setSpy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
const result = service.createCodeVerifier({ configId: 'configId1' });
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(result.length).toBe(67);
|
||||
expect(setSpy).toHaveBeenCalledOnceWith('codeVerifier', result, {
|
||||
expect(setSpy).toHaveBeenCalledExactlyOnceWith('codeVerifier', result, {
|
||||
configId: 'configId1',
|
||||
});
|
||||
});
|
||||
@ -165,22 +179,26 @@ describe('Flows Data Service', () => {
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('storageCodeFlowInProgress', config)
|
||||
.and.returnValue(true);
|
||||
const spyWrite = spyOn(storagePersistenceService, 'write');
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['storageCodeFlowInProgress', config],
|
||||
() => true
|
||||
);
|
||||
const spyWrite = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
const isCodeFlowInProgressResult = service.isCodeFlowInProgress(config);
|
||||
|
||||
expect(spyWrite).not.toHaveBeenCalled();
|
||||
expect(isCodeFlowInProgressResult).toBeTrue();
|
||||
expect(isCodeFlowInProgressResult).toBeTruthy();
|
||||
});
|
||||
|
||||
it('state object does not exist returns false result', () => {
|
||||
// arrange
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('storageCodeFlowInProgress', { configId: 'configId1' })
|
||||
.and.returnValue(null);
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['storageCodeFlowInProgress', { configId: 'configId1' }],
|
||||
() => null
|
||||
);
|
||||
|
||||
// act
|
||||
const isCodeFlowInProgressResult = service.isCodeFlowInProgress({
|
||||
@ -188,7 +206,7 @@ describe('Flows Data Service', () => {
|
||||
});
|
||||
|
||||
// assert
|
||||
expect(isCodeFlowInProgressResult).toBeFalse();
|
||||
expect(isCodeFlowInProgressResult).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@ -200,23 +218,31 @@ describe('Flows Data Service', () => {
|
||||
|
||||
jasmine.clock().mockDate(baseTime);
|
||||
|
||||
const spy = spyOn(storagePersistenceService, 'write');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
service.setCodeFlowInProgress({ configId: 'configId1' });
|
||||
expect(spy).toHaveBeenCalledOnceWith('storageCodeFlowInProgress', true, {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageCodeFlowInProgress',
|
||||
true,
|
||||
{
|
||||
configId: 'configId1',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetCodeFlowInProgress', () => {
|
||||
it('set resetCodeFlowInProgress to false when called', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'write');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
service.resetCodeFlowInProgress({ configId: 'configId1' });
|
||||
expect(spy).toHaveBeenCalledOnceWith('storageCodeFlowInProgress', false, {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageCodeFlowInProgress',
|
||||
false,
|
||||
{
|
||||
configId: 'configId1',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -238,21 +264,21 @@ describe('Flows Data Service', () => {
|
||||
dateOfLaunchedProcessUtc: baseTime.toISOString(),
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
vi.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('storageSilentRenewRunning', config)
|
||||
.and.returnValue(JSON.stringify(storageObject));
|
||||
const spyWrite = spyOn(storagePersistenceService, 'write');
|
||||
.mockReturnValue(JSON.stringify(storageObject));
|
||||
const spyWrite = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
jasmine.clock().tick((config.silentRenewTimeoutInSeconds + 1) * 1000);
|
||||
|
||||
const isSilentRenewRunningResult = service.isSilentRenewRunning(config);
|
||||
|
||||
expect(spyWrite).toHaveBeenCalledOnceWith(
|
||||
expect(spyWrite).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageSilentRenewRunning',
|
||||
'',
|
||||
config
|
||||
);
|
||||
expect(isSilentRenewRunningResult).toBeFalse();
|
||||
expect(isSilentRenewRunningResult).toBeFalsy();
|
||||
});
|
||||
|
||||
it('checks silent renew process and returns result', () => {
|
||||
@ -272,27 +298,29 @@ describe('Flows Data Service', () => {
|
||||
dateOfLaunchedProcessUtc: baseTime.toISOString(),
|
||||
};
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
vi.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('storageSilentRenewRunning', config)
|
||||
.and.returnValue(JSON.stringify(storageObject));
|
||||
const spyWrite = spyOn(storagePersistenceService, 'write');
|
||||
.mockReturnValue(JSON.stringify(storageObject));
|
||||
const spyWrite = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
const isSilentRenewRunningResult = service.isSilentRenewRunning(config);
|
||||
|
||||
expect(spyWrite).not.toHaveBeenCalled();
|
||||
expect(isSilentRenewRunningResult).toBeTrue();
|
||||
expect(isSilentRenewRunningResult).toBeTruthy();
|
||||
});
|
||||
|
||||
it('state object does not exist returns false result', () => {
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('storageSilentRenewRunning', { configId: 'configId1' })
|
||||
.and.returnValue(null);
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['storageSilentRenewRunning', { configId: 'configId1' }],
|
||||
() => null
|
||||
);
|
||||
|
||||
const isSilentRenewRunningResult = service.isSilentRenewRunning({
|
||||
configId: 'configId1',
|
||||
});
|
||||
|
||||
expect(isSilentRenewRunningResult).toBeFalse();
|
||||
expect(isSilentRenewRunningResult).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@ -309,10 +337,10 @@ describe('Flows Data Service', () => {
|
||||
dateOfLaunchedProcessUtc: baseTime.toISOString(),
|
||||
};
|
||||
|
||||
const spy = spyOn(storagePersistenceService, 'write');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
service.setSilentRenewRunning({ configId: 'configId1' });
|
||||
expect(spy).toHaveBeenCalledOnceWith(
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageSilentRenewRunning',
|
||||
JSON.stringify(storageObject),
|
||||
{ configId: 'configId1' }
|
||||
@ -322,12 +350,16 @@ describe('Flows Data Service', () => {
|
||||
|
||||
describe('resetSilentRenewRunning', () => {
|
||||
it('set resetSilentRenewRunning to empty string when called', () => {
|
||||
const spy = spyOn(storagePersistenceService, 'write');
|
||||
const spy = vi.spyOn(storagePersistenceService, 'write');
|
||||
|
||||
service.resetSilentRenewRunning({ configId: 'configId1' });
|
||||
expect(spy).toHaveBeenCalledOnceWith('storageSilentRenewRunning', '', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageSilentRenewRunning',
|
||||
'',
|
||||
{
|
||||
configId: 'configId1',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { SilentRenewRunning } from './flows.models';
|
||||
import type { SilentRenewRunning } from './flows.models';
|
||||
import { RandomService } from './random/random.service';
|
||||
|
||||
@Injectable()
|
||||
@ -18,7 +18,7 @@ export class FlowsDataService {
|
||||
createNonce(configuration: OpenIdConfiguration): string {
|
||||
const nonce = this.randomService.createRandom(40, configuration);
|
||||
|
||||
this.loggerService.logDebug(configuration, 'Nonce created. nonce:' + nonce);
|
||||
this.loggerService.logDebug(configuration, `Nonce created. nonce:${nonce}`);
|
||||
this.setNonce(nonce, configuration);
|
||||
|
||||
return nonce;
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { CallbackContext } from './callback-context';
|
||||
import { vi } from 'vitest';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import type { CallbackContext } from './callback-context';
|
||||
import { CodeFlowCallbackHandlerService } from './callback-handling/code-flow-callback-handler.service';
|
||||
import { HistoryJwtKeysCallbackHandlerService } from './callback-handling/history-jwt-keys-callback-handler.service';
|
||||
import { ImplicitFlowCallbackHandlerService } from './callback-handling/implicit-flow-callback-handler.service';
|
||||
@ -64,27 +65,25 @@ describe('Flows Service', () => {
|
||||
});
|
||||
|
||||
describe('processCodeFlowCallback', () => {
|
||||
it('calls all methods correctly', waitForAsync(() => {
|
||||
const codeFlowCallbackSpy = spyOn(
|
||||
codeFlowCallbackHandlerService,
|
||||
'codeFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const codeFlowCodeRequestSpy = spyOn(
|
||||
codeFlowCallbackHandlerService,
|
||||
'codeFlowCodeRequest'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackHistoryAndResetJwtKeysSpy = spyOn(
|
||||
historyJwtKeysCallbackHandlerService,
|
||||
'callbackHistoryAndResetJwtKeys'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackStateValidationSpy = spyOn(
|
||||
stateValidationCallbackHandlerService,
|
||||
'callbackStateValidation'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackUserSpy = spyOn(
|
||||
userCallbackHandlerService,
|
||||
'callbackUser'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
it('calls all methods correctly', async () => {
|
||||
const codeFlowCallbackSpy = vi
|
||||
.spyOn(codeFlowCallbackHandlerService, 'codeFlowCallback')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const codeFlowCodeRequestSpy = vi
|
||||
.spyOn(codeFlowCallbackHandlerService, 'codeFlowCodeRequest')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackHistoryAndResetJwtKeysSpy = vi
|
||||
.spyOn(
|
||||
historyJwtKeysCallbackHandlerService,
|
||||
'callbackHistoryAndResetJwtKeys'
|
||||
)
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackStateValidationSpy = vi
|
||||
.spyOn(stateValidationCallbackHandlerService, 'callbackStateValidation')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackUserSpy = vi
|
||||
.spyOn(userCallbackHandlerService, 'callbackUser')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -92,10 +91,10 @@ describe('Flows Service', () => {
|
||||
];
|
||||
|
||||
service
|
||||
.processCodeFlowCallback('some-url1234', allConfigs[0], allConfigs)
|
||||
.processCodeFlowCallback('some-url1234', allConfigs[0]!, allConfigs)
|
||||
.subscribe((value) => {
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(codeFlowCallbackSpy).toHaveBeenCalledOnceWith(
|
||||
expect(codeFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url1234',
|
||||
allConfigs[0]
|
||||
);
|
||||
@ -104,27 +103,26 @@ describe('Flows Service', () => {
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalledTimes(1);
|
||||
expect(callbackUserSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('processSilentRenewCodeFlowCallback', () => {
|
||||
it('calls all methods correctly', waitForAsync(() => {
|
||||
const codeFlowCodeRequestSpy = spyOn(
|
||||
codeFlowCallbackHandlerService,
|
||||
'codeFlowCodeRequest'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackHistoryAndResetJwtKeysSpy = spyOn(
|
||||
historyJwtKeysCallbackHandlerService,
|
||||
'callbackHistoryAndResetJwtKeys'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackStateValidationSpy = spyOn(
|
||||
stateValidationCallbackHandlerService,
|
||||
'callbackStateValidation'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackUserSpy = spyOn(
|
||||
userCallbackHandlerService,
|
||||
'callbackUser'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
it('calls all methods correctly', async () => {
|
||||
const codeFlowCodeRequestSpy = vi
|
||||
.spyOn(codeFlowCallbackHandlerService, 'codeFlowCodeRequest')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackHistoryAndResetJwtKeysSpy = vi
|
||||
.spyOn(
|
||||
historyJwtKeysCallbackHandlerService,
|
||||
'callbackHistoryAndResetJwtKeys'
|
||||
)
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackStateValidationSpy = vi
|
||||
.spyOn(stateValidationCallbackHandlerService, 'callbackStateValidation')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackUserSpy = vi
|
||||
.spyOn(userCallbackHandlerService, 'callbackUser')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -134,7 +132,7 @@ describe('Flows Service', () => {
|
||||
service
|
||||
.processSilentRenewCodeFlowCallback(
|
||||
{} as CallbackContext,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
)
|
||||
.subscribe((value) => {
|
||||
@ -144,27 +142,26 @@ describe('Flows Service', () => {
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('processImplicitFlowCallback', () => {
|
||||
it('calls all methods correctly', waitForAsync(() => {
|
||||
const implicitFlowCallbackSpy = spyOn(
|
||||
implicitFlowCallbackHandlerService,
|
||||
'implicitFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackHistoryAndResetJwtKeysSpy = spyOn(
|
||||
historyJwtKeysCallbackHandlerService,
|
||||
'callbackHistoryAndResetJwtKeys'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackStateValidationSpy = spyOn(
|
||||
stateValidationCallbackHandlerService,
|
||||
'callbackStateValidation'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackUserSpy = spyOn(
|
||||
userCallbackHandlerService,
|
||||
'callbackUser'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
it('calls all methods correctly', async () => {
|
||||
const implicitFlowCallbackSpy = vi
|
||||
.spyOn(implicitFlowCallbackHandlerService, 'implicitFlowCallback')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackHistoryAndResetJwtKeysSpy = vi
|
||||
.spyOn(
|
||||
historyJwtKeysCallbackHandlerService,
|
||||
'callbackHistoryAndResetJwtKeys'
|
||||
)
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackStateValidationSpy = vi
|
||||
.spyOn(stateValidationCallbackHandlerService, 'callbackStateValidation')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackUserSpy = vi
|
||||
.spyOn(userCallbackHandlerService, 'callbackUser')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -172,7 +169,7 @@ describe('Flows Service', () => {
|
||||
];
|
||||
|
||||
service
|
||||
.processImplicitFlowCallback(allConfigs[0], allConfigs, 'any-hash')
|
||||
.processImplicitFlowCallback(allConfigs[0]!, allConfigs, 'any-hash')
|
||||
.subscribe((value) => {
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(implicitFlowCallbackSpy).toHaveBeenCalled();
|
||||
@ -180,31 +177,32 @@ describe('Flows Service', () => {
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('processRefreshToken', () => {
|
||||
it('calls all methods correctly', waitForAsync(() => {
|
||||
const refreshSessionWithRefreshTokensSpy = spyOn(
|
||||
refreshSessionCallbackHandlerService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const refreshTokensRequestTokensSpy = spyOn(
|
||||
refreshTokenCallbackHandlerService,
|
||||
'refreshTokensRequestTokens'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackHistoryAndResetJwtKeysSpy = spyOn(
|
||||
historyJwtKeysCallbackHandlerService,
|
||||
'callbackHistoryAndResetJwtKeys'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackStateValidationSpy = spyOn(
|
||||
stateValidationCallbackHandlerService,
|
||||
'callbackStateValidation'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const callbackUserSpy = spyOn(
|
||||
userCallbackHandlerService,
|
||||
'callbackUser'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
it('calls all methods correctly', async () => {
|
||||
const refreshSessionWithRefreshTokensSpy = vi
|
||||
.spyOn(
|
||||
refreshSessionCallbackHandlerService,
|
||||
'refreshSessionWithRefreshTokens'
|
||||
)
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const refreshTokensRequestTokensSpy = vi
|
||||
.spyOn(refreshTokenCallbackHandlerService, 'refreshTokensRequestTokens')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackHistoryAndResetJwtKeysSpy = vi
|
||||
.spyOn(
|
||||
historyJwtKeysCallbackHandlerService,
|
||||
'callbackHistoryAndResetJwtKeys'
|
||||
)
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackStateValidationSpy = vi
|
||||
.spyOn(stateValidationCallbackHandlerService, 'callbackStateValidation')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const callbackUserSpy = vi
|
||||
.spyOn(userCallbackHandlerService, 'callbackUser')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const allConfigs = [
|
||||
{
|
||||
configId: 'configId1',
|
||||
@ -212,7 +210,7 @@ describe('Flows Service', () => {
|
||||
];
|
||||
|
||||
service
|
||||
.processRefreshToken(allConfigs[0], allConfigs)
|
||||
.processRefreshToken(allConfigs[0]!, allConfigs)
|
||||
.subscribe((value) => {
|
||||
expect(value).toEqual({} as CallbackContext);
|
||||
expect(refreshSessionWithRefreshTokensSpy).toHaveBeenCalled();
|
||||
@ -221,6 +219,6 @@ describe('Flows Service', () => {
|
||||
expect(callbackStateValidationSpy).toHaveBeenCalled();
|
||||
expect(callbackUserSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { concatMap } from 'rxjs/operators';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CallbackContext } from './callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { CallbackContext } from './callback-context';
|
||||
import { CodeFlowCallbackHandlerService } from './callback-handling/code-flow-callback-handler.service';
|
||||
import { HistoryJwtKeysCallbackHandlerService } from './callback-handling/history-jwt-keys-callback-handler.service';
|
||||
import { ImplicitFlowCallbackHandlerService } from './callback-handling/implicit-flow-callback-handler.service';
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { CryptoService } from '../../utils/crypto/crypto.service';
|
||||
import { RandomService } from './random.service';
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { UserService } from '../user-data/user.service';
|
||||
import { FlowsDataService } from './flows-data.service';
|
||||
import { ResetAuthDataService } from './reset-auth-data.service';
|
||||
@ -37,7 +38,7 @@ describe('ResetAuthDataService', () => {
|
||||
|
||||
describe('resetAuthorizationData', () => {
|
||||
it('calls resetUserDataInStore when autoUserInfo is true', () => {
|
||||
const resetUserDataInStoreSpy = spyOn(
|
||||
const resetUserDataInStoreSpy = vi.spyOn(
|
||||
userService,
|
||||
'resetUserDataInStore'
|
||||
);
|
||||
@ -47,16 +48,16 @@ describe('ResetAuthDataService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
service.resetAuthorizationData(allConfigs[0], allConfigs);
|
||||
service.resetAuthorizationData(allConfigs[0]!, allConfigs);
|
||||
expect(resetUserDataInStoreSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls correct methods', () => {
|
||||
const resetStorageFlowDataSpy = spyOn(
|
||||
const resetStorageFlowDataSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetStorageFlowData'
|
||||
);
|
||||
const setUnauthorizedAndFireEventSpy = spyOn(
|
||||
const setUnauthorizedAndFireEventSpy = vi.spyOn(
|
||||
authStateService,
|
||||
'setUnauthenticatedAndFireEvent'
|
||||
);
|
||||
@ -66,7 +67,7 @@ describe('ResetAuthDataService', () => {
|
||||
},
|
||||
];
|
||||
|
||||
service.resetAuthorizationData(allConfigs[0], allConfigs);
|
||||
service.resetAuthorizationData(allConfigs[0]!, allConfigs);
|
||||
|
||||
expect(resetStorageFlowDataSpy).toHaveBeenCalled();
|
||||
expect(setUnauthorizedAndFireEventSpy).toHaveBeenCalled();
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { UserService } from '../user-data/user.service';
|
||||
import { FlowsDataService } from './flows-data.service';
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { HttpResponse } from '@angular/common/http';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { HttpResponse } from '@ngify/http';
|
||||
import { isObservable, of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { createRetriableStream } from '../../test/create-retriable-stream.helper';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../api/data.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { createRetriableStream } from '../testing/create-retriable-stream.helper';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { SigninKeyDataService } from './signin-key-data.service';
|
||||
|
||||
const DUMMY_JWKS = {
|
||||
@ -53,10 +54,12 @@ describe('Signin Key Data Service', () => {
|
||||
});
|
||||
|
||||
describe('getSigningKeys', () => {
|
||||
it('throws error when no wellKnownEndpoints given', waitForAsync(() => {
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue(null);
|
||||
it('throws error when no wellKnownEndpoints given', async () => {
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => null
|
||||
);
|
||||
const result = service.getSigningKeys({ configId: 'configId1' });
|
||||
|
||||
result.subscribe({
|
||||
@ -64,12 +67,14 @@ describe('Signin Key Data Service', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws error when no jwksUri given', waitForAsync(() => {
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ jwksUri: null });
|
||||
it('throws error when no jwksUri given', async () => {
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ jwksUri: null })
|
||||
);
|
||||
const result = service.getSigningKeys({ configId: 'configId1' });
|
||||
|
||||
result.subscribe({
|
||||
@ -77,30 +82,34 @@ describe('Signin Key Data Service', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls dataservice if jwksurl is given', waitForAsync(() => {
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ jwksUri: 'someUrl' });
|
||||
const spy = spyOn(dataService, 'get').and.callFake(() => of());
|
||||
it('calls dataservice if jwksurl is given', async () => {
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ jwksUri: 'someUrl' })
|
||||
);
|
||||
const spy = vi.spyOn(dataService, 'get').mockImplementation(() => of());
|
||||
|
||||
const result = service.getSigningKeys({ configId: 'configId1' });
|
||||
|
||||
result.subscribe({
|
||||
complete: () => {
|
||||
expect(spy).toHaveBeenCalledOnceWith('someUrl', {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('someUrl', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry once', waitForAsync(() => {
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ jwksUri: 'someUrl' });
|
||||
spyOn(dataService, 'get').and.returnValue(
|
||||
it('should retry once', async () => {
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ jwksUri: 'someUrl' })
|
||||
);
|
||||
vi.spyOn(dataService, 'get').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('Error')),
|
||||
of(DUMMY_JWKS)
|
||||
@ -113,13 +122,15 @@ describe('Signin Key Data Service', () => {
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry twice', waitForAsync(() => {
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ jwksUri: 'someUrl' });
|
||||
spyOn(dataService, 'get').and.returnValue(
|
||||
it('should retry twice', async () => {
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ jwksUri: 'someUrl' })
|
||||
);
|
||||
vi.spyOn(dataService, 'get').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('Error')),
|
||||
throwError(() => new Error('Error')),
|
||||
@ -133,13 +144,15 @@ describe('Signin Key Data Service', () => {
|
||||
expect(res).toEqual(DUMMY_JWKS);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should fail after three tries', waitForAsync(() => {
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ jwksUri: 'someUrl' });
|
||||
spyOn(dataService, 'get').and.returnValue(
|
||||
it('should fail after three tries', async () => {
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ jwksUri: 'someUrl' })
|
||||
);
|
||||
vi.spyOn(dataService, 'get').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('Error')),
|
||||
throwError(() => new Error('Error')),
|
||||
@ -153,21 +166,21 @@ describe('Signin Key Data Service', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleErrorGetSigningKeys', () => {
|
||||
it('keeps observable if error is catched', waitForAsync(() => {
|
||||
it('keeps observable if error is catched', async () => {
|
||||
const result = (service as any).handleErrorGetSigningKeys(
|
||||
new HttpResponse()
|
||||
);
|
||||
const hasTypeObservable = isObservable(result);
|
||||
|
||||
expect(hasTypeObservable).toBeTrue();
|
||||
}));
|
||||
expect(hasTypeObservable).toBeTruthy();
|
||||
});
|
||||
|
||||
it('logs error if error is response', waitForAsync(() => {
|
||||
const logSpy = spyOn(loggerService, 'logError');
|
||||
it('logs error if error is response', async () => {
|
||||
const logSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
(service as any)
|
||||
.handleErrorGetSigningKeys(
|
||||
@ -176,31 +189,31 @@ describe('Signin Key Data Service', () => {
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(logSpy).toHaveBeenCalledOnceWith(
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'400 - nono {}'
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('logs error if error is not a response', waitForAsync(() => {
|
||||
const logSpy = spyOn(loggerService, 'logError');
|
||||
it('logs error if error is not a response', async () => {
|
||||
const logSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
(service as any)
|
||||
.handleErrorGetSigningKeys('Just some Error', { configId: 'configId1' })
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(logSpy).toHaveBeenCalledOnceWith(
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('logs error if error with message property is not a response', waitForAsync(() => {
|
||||
const logSpy = spyOn(loggerService, 'logError');
|
||||
it('logs error if error with message property is not a response', async () => {
|
||||
const logSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
(service as any)
|
||||
.handleErrorGetSigningKeys(
|
||||
@ -209,12 +222,12 @@ describe('Signin Key Data Service', () => {
|
||||
)
|
||||
.subscribe({
|
||||
error: () => {
|
||||
expect(logSpy).toHaveBeenCalledOnceWith(
|
||||
expect(logSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Just some Error'
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
11
src/http/index.ts
Normal file
11
src/http/index.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import type { HttpFeature } from '@ngify/http';
|
||||
|
||||
export function provideHttpClient() {
|
||||
// todo
|
||||
throw new Error('todo!');
|
||||
}
|
||||
|
||||
export function withInterceptorsFromDi(): HttpFeature {
|
||||
// todo
|
||||
throw new Error('todo!');
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { skip } from 'rxjs/operators';
|
||||
import { mockAbstractProvider, mockProvider } from '../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { OidcSecurityService } from '../oidc.security.service';
|
||||
import { PublicEventsService } from '../public-events/public-events.service';
|
||||
import { AbstractSecurityStorage } from '../storage/abstract-security-storage';
|
||||
import { DefaultSessionStorageService } from '../storage/default-sessionstorage.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { mockAbstractProvider, mockProvider } from '../testing/mock';
|
||||
import { PlatformProvider } from '../utils/platform-provider/platform.provider';
|
||||
import { CheckSessionService } from './check-session.service';
|
||||
import { IFrameService } from './existing-iframe.service';
|
||||
@ -67,7 +68,7 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
it('getOrCreateIframe calls iFrameService.addIFrameToWindowBody if no Iframe exists', () => {
|
||||
spyOn(iFrameService, 'addIFrameToWindowBody').and.callThrough();
|
||||
vi.spyOn(iFrameService, 'addIFrameToWindowBody')();
|
||||
|
||||
const result = (checkSessionService as any).getOrCreateIframe({
|
||||
configId: 'configId1',
|
||||
@ -89,7 +90,7 @@ describe('CheckSessionService', () => {
|
||||
|
||||
it('init appends iframe on body with correct values', () => {
|
||||
expect((checkSessionService as any).sessionIframe).toBeFalsy();
|
||||
spyOn<any>(loggerService, 'logDebug').and.callFake(() => undefined);
|
||||
vi.spyOn(loggerService, 'logDebug').mockImplementation(() => undefined);
|
||||
|
||||
(checkSessionService as any).init();
|
||||
const iframe = (checkSessionService as any).getOrCreateIframe({
|
||||
@ -105,29 +106,34 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
it('log warning if authWellKnownEndpoints.check_session_iframe is not existing', () => {
|
||||
const spyLogWarning = spyOn<any>(loggerService, 'logWarning');
|
||||
const spyLogWarning = vi.spyOn<any>(loggerService, 'logWarning');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn<any>(loggerService, 'logDebug').and.callFake(() => undefined);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
vi.spyOn<any>(loggerService, 'logDebug').mockImplementation(
|
||||
() => undefined
|
||||
);
|
||||
vi.spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ checkSessionIframe: undefined });
|
||||
.mockReturnValue({ checkSessionIframe: undefined });
|
||||
(checkSessionService as any).init(config);
|
||||
|
||||
expect(spyLogWarning).toHaveBeenCalledOnceWith(config, jasmine.any(String));
|
||||
expect(spyLogWarning).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
expect.any(String)
|
||||
);
|
||||
});
|
||||
|
||||
it('start() calls pollserversession() with clientId if no scheduledheartbeat is set', () => {
|
||||
const spy = spyOn<any>(checkSessionService, 'pollServerSession');
|
||||
const spy = vi.spyOn<any>(checkSessionService, 'pollServerSession');
|
||||
const config = { clientId: 'clientId', configId: 'configId1' };
|
||||
|
||||
checkSessionService.start(config);
|
||||
expect(spy).toHaveBeenCalledOnceWith('clientId', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('clientId', config);
|
||||
});
|
||||
|
||||
it('start() does not call pollServerSession() if scheduledHeartBeatRunning is set', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const spy = spyOn<any>(checkSessionService, 'pollServerSession');
|
||||
const spy = vi.spyOn<any>(checkSessionService, 'pollServerSession');
|
||||
|
||||
(checkSessionService as any).scheduledHeartBeatRunning = (): void =>
|
||||
undefined;
|
||||
@ -148,10 +154,10 @@ describe('CheckSessionService', () => {
|
||||
|
||||
it('stopCheckingSession does nothing if scheduledHeartBeatRunning is not set', () => {
|
||||
(checkSessionService as any).scheduledHeartBeatRunning = null;
|
||||
const spy = spyOn<any>(checkSessionService, 'clearScheduledHeartBeat');
|
||||
const spy = vi.spyOn<any>(checkSessionService, 'clearScheduledHeartBeat');
|
||||
|
||||
checkSessionService.stop();
|
||||
expect(spy).not.toHaveBeenCalledOnceWith();
|
||||
expect(spy).not.toHaveBeenCalledExactlyOnceWith();
|
||||
});
|
||||
|
||||
describe('serverStateChanged', () => {
|
||||
@ -167,7 +173,7 @@ describe('CheckSessionService', () => {
|
||||
const config = { startCheckSession: true, configId: 'configId1' };
|
||||
const result = checkSessionService.serverStateChanged(config);
|
||||
|
||||
expect(result).toBeFalse();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns true if startCheckSession is configured and checkSessionReceived is true', () => {
|
||||
@ -175,17 +181,17 @@ describe('CheckSessionService', () => {
|
||||
const config = { startCheckSession: true, configId: 'configId1' };
|
||||
const result = checkSessionService.serverStateChanged(config);
|
||||
|
||||
expect(result).toBeTrue();
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('pollServerSession', () => {
|
||||
beforeEach(() => {
|
||||
spyOn<any>(checkSessionService, 'init').and.returnValue(of(undefined));
|
||||
vi.spyOn<any>(checkSessionService, 'init').mockReturnValue(of(undefined));
|
||||
});
|
||||
|
||||
it('increases outstandingMessages', () => {
|
||||
spyOn<any>(checkSessionService, 'getExistingIframe').and.returnValue({
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue({
|
||||
contentWindow: { postMessage: () => undefined },
|
||||
});
|
||||
const authWellKnownEndpoints = {
|
||||
@ -193,18 +199,20 @@ describe('CheckSessionService', () => {
|
||||
};
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue(authWellKnownEndpoints)
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
)
|
||||
.withArgs('session_state', config)
|
||||
.and.returnValue('session_state');
|
||||
spyOn(loggerService, 'logDebug').and.callFake(() => undefined);
|
||||
.mockReturnValue('session_state');
|
||||
vi.spyOn(loggerService, 'logDebug').mockImplementation(() => undefined);
|
||||
(checkSessionService as any).pollServerSession('clientId', config);
|
||||
expect((checkSessionService as any).outstandingMessages).toBe(1);
|
||||
});
|
||||
|
||||
it('logs warning if iframe does not exist', () => {
|
||||
spyOn<any>(checkSessionService, 'getExistingIframe').and.returnValue(
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue(
|
||||
null
|
||||
);
|
||||
const authWellKnownEndpoints = {
|
||||
@ -212,77 +220,91 @@ describe('CheckSessionService', () => {
|
||||
};
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue(authWellKnownEndpoints);
|
||||
const spyLogWarning = spyOn(loggerService, 'logWarning').and.callFake(
|
||||
() => undefined
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
);
|
||||
const spyLogWarning = vi
|
||||
.spyOn(loggerService, 'logWarning')
|
||||
.mockImplementation(() => undefined);
|
||||
|
||||
spyOn(loggerService, 'logDebug').and.callFake(() => undefined);
|
||||
vi.spyOn(loggerService, 'logDebug').mockImplementation(() => undefined);
|
||||
(checkSessionService as any).pollServerSession('clientId', config);
|
||||
expect(spyLogWarning).toHaveBeenCalledOnceWith(
|
||||
expect(spyLogWarning).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
jasmine.any(String)
|
||||
expect.any(String)
|
||||
);
|
||||
});
|
||||
|
||||
it('logs warning if clientId is not set', () => {
|
||||
spyOn<any>(checkSessionService, 'getExistingIframe').and.returnValue({});
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue(
|
||||
{}
|
||||
);
|
||||
const authWellKnownEndpoints = {
|
||||
checkSessionIframe: 'https://some-testing-url.com',
|
||||
};
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue(authWellKnownEndpoints);
|
||||
const spyLogWarning = spyOn(loggerService, 'logWarning').and.callFake(
|
||||
() => undefined
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
);
|
||||
const spyLogWarning = vi
|
||||
.spyOn(loggerService, 'logWarning')
|
||||
.mockImplementation(() => undefined);
|
||||
|
||||
spyOn(loggerService, 'logDebug').and.callFake(() => undefined);
|
||||
vi.spyOn(loggerService, 'logDebug').mockImplementation(() => undefined);
|
||||
(checkSessionService as any).pollServerSession('', config);
|
||||
expect(spyLogWarning).toHaveBeenCalledOnceWith(
|
||||
expect(spyLogWarning).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
jasmine.any(String)
|
||||
expect.any(String)
|
||||
);
|
||||
});
|
||||
|
||||
it('logs debug if session_state is not set', () => {
|
||||
spyOn<any>(checkSessionService, 'getExistingIframe').and.returnValue({});
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue(
|
||||
{}
|
||||
);
|
||||
const authWellKnownEndpoints = {
|
||||
checkSessionIframe: 'https://some-testing-url.com',
|
||||
};
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue(authWellKnownEndpoints)
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
)
|
||||
.withArgs('session_state', config)
|
||||
.and.returnValue(null);
|
||||
.mockReturnValue(null);
|
||||
|
||||
const spyLogDebug = spyOn(loggerService, 'logDebug').and.callFake(
|
||||
() => undefined
|
||||
);
|
||||
const spyLogDebug = vi
|
||||
.spyOn(loggerService, 'logDebug')
|
||||
.mockImplementation(() => undefined);
|
||||
|
||||
(checkSessionService as any).pollServerSession('clientId', config);
|
||||
expect(spyLogDebug).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('logs debug if session_state is set but authWellKnownEndpoints are not set', () => {
|
||||
spyOn<any>(checkSessionService, 'getExistingIframe').and.returnValue({});
|
||||
vi.spyOn<any>(checkSessionService, 'getExistingIframe').mockReturnValue(
|
||||
{}
|
||||
);
|
||||
const authWellKnownEndpoints = null;
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue(authWellKnownEndpoints)
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => authWellKnownEndpoints
|
||||
)
|
||||
.withArgs('session_state', config)
|
||||
.and.returnValue('some_session_state');
|
||||
const spyLogDebug = spyOn(loggerService, 'logDebug').and.callFake(
|
||||
() => undefined
|
||||
);
|
||||
.mockReturnValue('some_session_state');
|
||||
const spyLogDebug = vi
|
||||
.spyOn(loggerService, 'logDebug')
|
||||
.mockImplementation(() => undefined);
|
||||
|
||||
(checkSessionService as any).pollServerSession('clientId', config);
|
||||
expect(spyLogDebug).toHaveBeenCalledTimes(2);
|
||||
@ -290,7 +312,7 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
describe('init', () => {
|
||||
it('returns falsy observable when lastIframerefresh and iframeRefreshInterval are bigger than now', waitForAsync(() => {
|
||||
it('returns falsy observable when lastIframerefresh and iframeRefreshInterval are bigger than now', async () => {
|
||||
const serviceAsAny = checkSessionService as any;
|
||||
const dateNow = new Date();
|
||||
const lastRefresh = dateNow.setMinutes(dateNow.getMinutes() + 30);
|
||||
@ -301,7 +323,7 @@ describe('CheckSessionService', () => {
|
||||
serviceAsAny.init().subscribe((result: any) => {
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('isCheckSessionConfigured', () => {
|
||||
@ -323,7 +345,7 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
describe('checkSessionChanged$', () => {
|
||||
it('emits when internal event is thrown', waitForAsync(() => {
|
||||
it('emits when internal event is thrown', async () => {
|
||||
checkSessionService.checkSessionChanged$
|
||||
.pipe(skip(1))
|
||||
.subscribe((result) => {
|
||||
@ -333,15 +355,15 @@ describe('CheckSessionService', () => {
|
||||
const serviceAsAny = checkSessionService as any;
|
||||
|
||||
serviceAsAny.checkSessionChangedInternal$.next(true);
|
||||
}));
|
||||
});
|
||||
|
||||
it('emits false initially', waitForAsync(() => {
|
||||
it('emits false initially', async () => {
|
||||
checkSessionService.checkSessionChanged$.subscribe((result) => {
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('emits false then true when emitted', waitForAsync(() => {
|
||||
it('emits false then true when emitted', async () => {
|
||||
const expectedResultsInOrder = [false, true];
|
||||
let counter = 0;
|
||||
|
||||
@ -351,6 +373,6 @@ describe('CheckSessionService', () => {
|
||||
});
|
||||
|
||||
(checkSessionService as any).checkSessionChangedInternal$.next(true);
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { UrlService } from '../utils/url/url.service';
|
||||
import { RefreshSessionIframeService } from './refresh-session-iframe.service';
|
||||
import { SilentRenewService } from './silent-renew.service';
|
||||
@ -31,37 +32,43 @@ describe('RefreshSessionIframeService ', () => {
|
||||
});
|
||||
|
||||
describe('refreshSessionWithIframe', () => {
|
||||
it('calls sendAuthorizeRequestUsingSilentRenew with created url', waitForAsync(() => {
|
||||
spyOn(urlService, 'getRefreshSessionSilentRenewUrl').and.returnValue(
|
||||
it('calls sendAuthorizeRequestUsingSilentRenew with created url', async () => {
|
||||
vi.spyOn(urlService, 'getRefreshSessionSilentRenewUrl').mockReturnValue(
|
||||
of('a-url')
|
||||
);
|
||||
const sendAuthorizeRequestUsingSilentRenewSpy = spyOn(
|
||||
refreshSessionIframeService as any,
|
||||
'sendAuthorizeRequestUsingSilentRenew'
|
||||
).and.returnValue(of(null));
|
||||
const sendAuthorizeRequestUsingSilentRenewSpy = vi
|
||||
.spyOn(
|
||||
refreshSessionIframeService as any,
|
||||
'sendAuthorizeRequestUsingSilentRenew'
|
||||
)
|
||||
.mockReturnValue(of(null));
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
refreshSessionIframeService
|
||||
.refreshSessionWithIframe(allConfigs[0], allConfigs)
|
||||
.refreshSessionWithIframe(allConfigs[0]!, allConfigs)
|
||||
.subscribe(() => {
|
||||
expect(
|
||||
sendAuthorizeRequestUsingSilentRenewSpy
|
||||
).toHaveBeenCalledOnceWith('a-url', allConfigs[0], allConfigs);
|
||||
).toHaveBeenCalledExactlyOnceWith(
|
||||
'a-url',
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('initSilentRenewRequest', () => {
|
||||
it('dispatches customevent to window object', waitForAsync(() => {
|
||||
const dispatchEventSpy = spyOn(window, 'dispatchEvent');
|
||||
it('dispatches customevent to window object', async () => {
|
||||
const dispatchEventSpy = vi.spyOn(window, 'dispatchEvent');
|
||||
|
||||
(refreshSessionIframeService as any).initSilentRenewRequest();
|
||||
|
||||
expect(dispatchEventSpy).toHaveBeenCalledOnceWith(
|
||||
expect(dispatchEventSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
new CustomEvent('oidc-silent-renew-init', {
|
||||
detail: jasmine.any(Number),
|
||||
detail: expect.any(Number),
|
||||
})
|
||||
);
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { DOCUMENT } from '../dom';
|
||||
import { Injectable, RendererFactory2, inject } from 'injection-js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { DOCUMENT } from '../dom';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { UrlService } from '../utils/url/url.service';
|
||||
import { SilentRenewService } from './silent-renew.service';
|
||||
|
@ -1,14 +1,15 @@
|
||||
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, fakeAsync, tick } from '@/testing';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { ImplicitFlowCallbackService } from '../callback/implicit-flow-callback.service';
|
||||
import { IntervalService } from '../callback/interval.service';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { FlowsService } from '../flows/flows.service';
|
||||
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { FlowHelper } from '../utils/flowHelper/flow-helper.service';
|
||||
import { ValidationResult } from '../validation/validation-result';
|
||||
import { IFrameService } from './existing-iframe.service';
|
||||
@ -63,7 +64,7 @@ describe('SilentRenewService ', () => {
|
||||
describe('refreshSessionWithIFrameCompleted', () => {
|
||||
it('is of type observable', () => {
|
||||
expect(silentRenewService.refreshSessionWithIFrameCompleted$).toEqual(
|
||||
jasmine.any(Observable)
|
||||
expect.any(Observable)
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -95,7 +96,7 @@ describe('SilentRenewService ', () => {
|
||||
|
||||
describe('getOrCreateIframe', () => {
|
||||
it('returns iframe if iframe is truthy', () => {
|
||||
spyOn(silentRenewService as any, 'getExistingIframe').and.returnValue({
|
||||
vi.spyOn(silentRenewService as any, 'getExistingIframe').mockReturnValue({
|
||||
name: 'anything',
|
||||
});
|
||||
|
||||
@ -109,31 +110,33 @@ describe('SilentRenewService ', () => {
|
||||
it('adds iframe to body if existing iframe is falsy', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(silentRenewService as any, 'getExistingIframe').and.returnValue(
|
||||
vi.spyOn(silentRenewService as any, 'getExistingIframe').mockReturnValue(
|
||||
null
|
||||
);
|
||||
|
||||
const spy = spyOn(iFrameService, 'addIFrameToWindowBody').and.returnValue(
|
||||
{ name: 'anything' } as HTMLIFrameElement
|
||||
);
|
||||
const spy = vi
|
||||
.spyOn(iFrameService, 'addIFrameToWindowBody')
|
||||
.mockReturnValue({ name: 'anything' } as HTMLIFrameElement);
|
||||
|
||||
const result = silentRenewService.getOrCreateIframe(config);
|
||||
|
||||
expect(result).toEqual({ name: 'anything' } as HTMLIFrameElement);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
expect(spy).toHaveBeenCalledOnceWith('myiFrameForSilentRenew', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'myiFrameForSilentRenew',
|
||||
config
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('codeFlowCallbackSilentRenewIframe', () => {
|
||||
it('calls processSilentRenewCodeFlowCallback with correct arguments', waitForAsync(() => {
|
||||
it('calls processSilentRenewCodeFlowCallback with correct arguments', async () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const allConfigs = [config];
|
||||
|
||||
const spy = spyOn(
|
||||
flowsService,
|
||||
'processSilentRenewCodeFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const spy = vi
|
||||
.spyOn(flowsService, 'processSilentRenewCodeFlowCallback')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const expectedContext = {
|
||||
code: 'some-code',
|
||||
refreshToken: '',
|
||||
@ -152,32 +155,31 @@ describe('SilentRenewService ', () => {
|
||||
silentRenewService
|
||||
.codeFlowCallbackSilentRenewIframe([url, urlParts], config, allConfigs)
|
||||
.subscribe(() => {
|
||||
expect(spy).toHaveBeenCalledOnceWith(
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
expectedContext,
|
||||
config,
|
||||
allConfigs
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws error if url has error param and resets everything on error', waitForAsync(() => {
|
||||
it('throws error if url has error param and resets everything on error', async () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const allConfigs = [config];
|
||||
|
||||
const spy = spyOn(
|
||||
flowsService,
|
||||
'processSilentRenewCodeFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
const authStateServiceSpy = spyOn(
|
||||
const spy = vi
|
||||
.spyOn(flowsService, 'processSilentRenewCodeFlowCallback')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const authStateServiceSpy = vi.spyOn(
|
||||
authStateService,
|
||||
'updateAndPublishAuthState'
|
||||
);
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
const setNonceSpy = spyOn(flowsDataService, 'setNonce');
|
||||
const stopPeriodicTokenCheckSpy = spyOn(
|
||||
const setNonceSpy = vi.spyOn(flowsDataService, 'setNonce');
|
||||
const stopPeriodicTokenCheckSpy = vi.spyOn(
|
||||
intervalService,
|
||||
'stopPeriodicTokenCheck'
|
||||
);
|
||||
@ -191,121 +193,116 @@ describe('SilentRenewService ', () => {
|
||||
error: (error) => {
|
||||
expect(error).toEqual(new Error('some_error'));
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
expect(authStateServiceSpy).toHaveBeenCalledOnceWith({
|
||||
expect(authStateServiceSpy).toHaveBeenCalledExactlyOnceWith({
|
||||
isAuthenticated: false,
|
||||
validationResult: ValidationResult.LoginRequired,
|
||||
isRenewProcess: true,
|
||||
});
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledOnceWith(
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
allConfigs
|
||||
);
|
||||
expect(setNonceSpy).toHaveBeenCalledOnceWith('', config);
|
||||
expect(setNonceSpy).toHaveBeenCalledExactlyOnceWith('', config);
|
||||
expect(stopPeriodicTokenCheckSpy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('silentRenewEventHandler', () => {
|
||||
it('returns if no details is given', fakeAsync(() => {
|
||||
const isCurrentFlowCodeFlowSpy = spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlow'
|
||||
).and.returnValue(false);
|
||||
it('returns if no details is given', async () => {
|
||||
const isCurrentFlowCodeFlowSpy = vi
|
||||
.spyOn(flowHelper, 'isCurrentFlowCodeFlow')
|
||||
.mockReturnValue(false);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
implicitFlowCallbackService,
|
||||
'authenticatedImplicitFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
).mockReturnValue(of({} as CallbackContext));
|
||||
const eventData = { detail: null } as CustomEvent;
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
silentRenewService.silentRenewEventHandler(
|
||||
eventData,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
tick(1000);
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
expect(isCurrentFlowCodeFlowSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls authorizedImplicitFlowCallback if current flow is not code flow', fakeAsync(() => {
|
||||
const isCurrentFlowCodeFlowSpy = spyOn(
|
||||
flowHelper,
|
||||
'isCurrentFlowCodeFlow'
|
||||
).and.returnValue(false);
|
||||
const authorizedImplicitFlowCallbackSpy = spyOn(
|
||||
implicitFlowCallbackService,
|
||||
'authenticatedImplicitFlowCallback'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
it('calls authorizedImplicitFlowCallback if current flow is not code flow', async () => {
|
||||
const isCurrentFlowCodeFlowSpy = vi
|
||||
.spyOn(flowHelper, 'isCurrentFlowCodeFlow')
|
||||
.mockReturnValue(false);
|
||||
const authorizedImplicitFlowCallbackSpy = vi
|
||||
.spyOn(implicitFlowCallbackService, 'authenticatedImplicitFlowCallback')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const eventData = { detail: 'detail' } as CustomEvent;
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
silentRenewService.silentRenewEventHandler(
|
||||
eventData,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
tick(1000);
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
expect(isCurrentFlowCodeFlowSpy).toHaveBeenCalled();
|
||||
expect(authorizedImplicitFlowCallbackSpy).toHaveBeenCalledOnceWith(
|
||||
allConfigs[0],
|
||||
expect(authorizedImplicitFlowCallbackSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
allConfigs[0]!,
|
||||
allConfigs,
|
||||
'detail'
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls codeFlowCallbackSilentRenewIframe if current flow is code flow', fakeAsync(() => {
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
|
||||
const codeFlowCallbackSilentRenewIframe = spyOn(
|
||||
silentRenewService,
|
||||
'codeFlowCallbackSilentRenewIframe'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
it('calls codeFlowCallbackSilentRenewIframe if current flow is code flow', async () => {
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
|
||||
const codeFlowCallbackSilentRenewIframe = vi
|
||||
.spyOn(silentRenewService, 'codeFlowCallbackSilentRenewIframe')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const eventData = { detail: 'detail?detail2' } as CustomEvent;
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
silentRenewService.silentRenewEventHandler(
|
||||
eventData,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
tick(1000);
|
||||
expect(codeFlowCallbackSilentRenewIframe).toHaveBeenCalledOnceWith(
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
expect(codeFlowCallbackSilentRenewIframe).toHaveBeenCalledExactlyOnceWith(
|
||||
['detail', 'detail2'],
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls authorizedImplicitFlowCallback if current flow is not code flow', fakeAsync(() => {
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
|
||||
const codeFlowCallbackSilentRenewIframe = spyOn(
|
||||
silentRenewService,
|
||||
'codeFlowCallbackSilentRenewIframe'
|
||||
).and.returnValue(of({} as CallbackContext));
|
||||
it('calls authorizedImplicitFlowCallback if current flow is not code flow', async () => {
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
|
||||
const codeFlowCallbackSilentRenewIframe = vi
|
||||
.spyOn(silentRenewService, 'codeFlowCallbackSilentRenewIframe')
|
||||
.mockReturnValue(of({} as CallbackContext));
|
||||
const eventData = { detail: 'detail?detail2' } as CustomEvent;
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
silentRenewService.silentRenewEventHandler(
|
||||
eventData,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
tick(1000);
|
||||
expect(codeFlowCallbackSilentRenewIframe).toHaveBeenCalledOnceWith(
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
expect(codeFlowCallbackSilentRenewIframe).toHaveBeenCalledExactlyOnceWith(
|
||||
['detail', 'detail2'],
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls next on refreshSessionWithIFrameCompleted with callbackcontext', fakeAsync(() => {
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
|
||||
spyOn(
|
||||
it('calls next on refreshSessionWithIFrameCompleted with callbackcontext', async () => {
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
silentRenewService,
|
||||
'codeFlowCallbackSilentRenewIframe'
|
||||
).and.returnValue(
|
||||
).mockReturnValue(
|
||||
of({ refreshToken: 'callbackContext' } as CallbackContext)
|
||||
);
|
||||
const eventData = { detail: 'detail?detail2' } as CustomEvent;
|
||||
@ -321,42 +318,42 @@ describe('SilentRenewService ', () => {
|
||||
|
||||
silentRenewService.silentRenewEventHandler(
|
||||
eventData,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
tick(1000);
|
||||
}));
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
});
|
||||
|
||||
it('loggs and calls flowsDataService.resetSilentRenewRunning in case of an error', fakeAsync(() => {
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
|
||||
spyOn(
|
||||
it('loggs and calls flowsDataService.resetSilentRenewRunning in case of an error', async () => {
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
silentRenewService,
|
||||
'codeFlowCallbackSilentRenewIframe'
|
||||
).and.returnValue(throwError(() => new Error('ERROR')));
|
||||
const resetSilentRenewRunningSpy = spyOn(
|
||||
).mockReturnValue(throwError(() => new Error('ERROR')));
|
||||
const resetSilentRenewRunningSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
const logErrorSpy = spyOn(loggerService, 'logError');
|
||||
const logErrorSpy = vi.spyOn(loggerService, 'logError');
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
const eventData = { detail: 'detail?detail2' } as CustomEvent;
|
||||
|
||||
silentRenewService.silentRenewEventHandler(
|
||||
eventData,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
tick(1000);
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
expect(resetSilentRenewRunningSpy).toHaveBeenCalledTimes(1);
|
||||
expect(logErrorSpy).toHaveBeenCalledTimes(1);
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls next on refreshSessionWithIFrameCompleted with null in case of error', fakeAsync(() => {
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
|
||||
spyOn(
|
||||
it('calls next on refreshSessionWithIFrameCompleted with null in case of error', async () => {
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
silentRenewService,
|
||||
'codeFlowCallbackSilentRenewIframe'
|
||||
).and.returnValue(throwError(() => new Error('ERROR')));
|
||||
).mockReturnValue(throwError(() => new Error('ERROR')));
|
||||
const eventData = { detail: 'detail?detail2' } as CustomEvent;
|
||||
const allConfigs = [{ configId: 'configId1' }];
|
||||
|
||||
@ -368,10 +365,10 @@ describe('SilentRenewService ', () => {
|
||||
|
||||
silentRenewService.silentRenewEventHandler(
|
||||
eventData,
|
||||
allConfigs[0],
|
||||
allConfigs[0]!,
|
||||
allConfigs
|
||||
);
|
||||
tick(1000);
|
||||
}));
|
||||
await vi.advanceTimersByTimeAsync(1000);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { HttpParams } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, Subject, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, Subject, throwError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { ImplicitFlowCallbackService } from '../callback/implicit-flow-callback.service';
|
||||
import { IntervalService } from '../callback/interval.service';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { CallbackContext } from '../flows/callback-context';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { CallbackContext } from '../flows/callback-context';
|
||||
import { FlowsDataService } from '../flows/flows-data.service';
|
||||
import { FlowsService } from '../flows/flows.service';
|
||||
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
|
||||
|
@ -5,7 +5,6 @@ export * from './auth-options';
|
||||
export * from './auth-state/auth-result';
|
||||
export * from './auth-state/auth-state';
|
||||
export * from './auth.module';
|
||||
export * from './auto-login/auto-login-all-routes.guard';
|
||||
export * from './auto-login/auto-login-partial-routes.guard';
|
||||
export * from './config/auth-well-known/auth-well-known-endpoints';
|
||||
export * from './config/config.service';
|
||||
@ -29,3 +28,5 @@ export * from './user-data/userdata-result';
|
||||
export * from './validation/jwtkeys';
|
||||
export * from './validation/state-validation-result';
|
||||
export * from './validation/validation-result';
|
||||
export * from './injection';
|
||||
export * from './router';
|
||||
|
7
src/injection/convention.ts
Normal file
7
src/injection/convention.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { InjectionToken } from 'injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
|
||||
export const APP_INITIALIZER = new InjectionToken<
|
||||
// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>
|
||||
readonly (() => void | Observable<unknown> | Promise<unknown>)[]
|
||||
>('APP_INITIALIZER');
|
3
src/injection/index.ts
Normal file
3
src/injection/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export { Module } from './module';
|
||||
export { APP_INITIALIZER } from './convention';
|
||||
export { injectAbstractType } from './inject';
|
10
src/injection/inject.ts
Normal file
10
src/injection/inject.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { inject } from 'injection-js';
|
||||
|
||||
// biome-ignore lint/complexity/noBannedTypes: <explanation>
|
||||
export interface AbstractType<T> extends Function {
|
||||
prototype: T;
|
||||
}
|
||||
|
||||
export function injectAbstractType<T>(abstractType: AbstractType<T>): T {
|
||||
return inject<T>(abstractType as any);
|
||||
}
|
4
src/injection/module.ts
Normal file
4
src/injection/module.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import 'reflect-metadata';
|
||||
import type { Injector } from 'injection-js';
|
||||
|
||||
export type Module = (parentInjector: Injector) => Injector;
|
@ -1,19 +1,20 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import {
|
||||
HTTP_INTERCEPTORS,
|
||||
HttpClient,
|
||||
provideHttpClient,
|
||||
withInterceptors,
|
||||
withInterceptorsFromDi,
|
||||
} from '@angular/common/http';
|
||||
} from '@ngify/http';
|
||||
import {
|
||||
HttpTestingController,
|
||||
provideHttpClientTesting,
|
||||
} from '@angular/common/http/testing';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
} from '@ngify/http/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { ConfigurationService } from '../config/config.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { AuthInterceptor, authInterceptor } from './auth.interceptor';
|
||||
import { ClosestMatchingRouteService } from './closest-matching-route.service';
|
||||
|
||||
@ -85,18 +86,22 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
});
|
||||
|
||||
function runTests(): void {
|
||||
it('should add an Authorization header when route matches and token is present', waitForAsync(() => {
|
||||
it('should add an Authorization header when route matches and token is present', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
|
||||
spyOn(configurationService, 'getAllConfigurations').and.returnValue([
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
secureRoutes: [actionUrl],
|
||||
configId: 'configId1',
|
||||
},
|
||||
]);
|
||||
|
||||
spyOn(authStateService, 'getAccessToken').and.returnValue('thisIsAToken');
|
||||
spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
|
||||
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
|
||||
'thisIsAToken'
|
||||
);
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
true
|
||||
);
|
||||
|
||||
httpClient.get(actionUrl).subscribe((response) => {
|
||||
expect(response).toBeTruthy();
|
||||
@ -108,18 +113,22 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
|
||||
httpRequest.flush('something');
|
||||
httpTestingController.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when `secureRoutes` is not given', waitForAsync(() => {
|
||||
it('should not add an Authorization header when `secureRoutes` is not given', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
|
||||
spyOn(configurationService, 'getAllConfigurations').and.returnValue([
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
configId: 'configId1',
|
||||
},
|
||||
]);
|
||||
spyOn(authStateService, 'getAccessToken').and.returnValue('thisIsAToken');
|
||||
spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
|
||||
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
|
||||
'thisIsAToken'
|
||||
);
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
true
|
||||
);
|
||||
|
||||
httpClient.get(actionUrl).subscribe((response) => {
|
||||
expect(response).toBeTruthy();
|
||||
@ -131,20 +140,24 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
|
||||
httpRequest.flush('something');
|
||||
httpTestingController.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when no routes configured', waitForAsync(() => {
|
||||
it('should not add an Authorization header when no routes configured', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
|
||||
spyOn(configurationService, 'getAllConfigurations').and.returnValue([
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
secureRoutes: [],
|
||||
configId: 'configId1',
|
||||
},
|
||||
]);
|
||||
|
||||
spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
|
||||
spyOn(authStateService, 'getAccessToken').and.returnValue('thisIsAToken');
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
true
|
||||
);
|
||||
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
|
||||
'thisIsAToken'
|
||||
);
|
||||
|
||||
httpClient.get(actionUrl).subscribe((response) => {
|
||||
expect(response).toBeTruthy();
|
||||
@ -156,19 +169,21 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
|
||||
httpRequest.flush('something');
|
||||
httpTestingController.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when no routes configured', waitForAsync(() => {
|
||||
it('should not add an Authorization header when no routes configured', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
|
||||
spyOn(configurationService, 'getAllConfigurations').and.returnValue([
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
secureRoutes: [],
|
||||
configId: 'configId1',
|
||||
},
|
||||
]);
|
||||
|
||||
spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
true
|
||||
);
|
||||
|
||||
httpClient.get(actionUrl).subscribe((response) => {
|
||||
expect(response).toBeTruthy();
|
||||
@ -180,20 +195,22 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
|
||||
httpRequest.flush('something');
|
||||
httpTestingController.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when route is configured but no token is present', waitForAsync(() => {
|
||||
it('should not add an Authorization header when route is configured but no token is present', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
|
||||
spyOn(configurationService, 'getAllConfigurations').and.returnValue([
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
secureRoutes: [actionUrl],
|
||||
configId: 'configId1',
|
||||
},
|
||||
]);
|
||||
|
||||
spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
|
||||
spyOn(authStateService, 'getAccessToken').and.returnValue('');
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
true
|
||||
);
|
||||
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue('');
|
||||
|
||||
httpClient.get(actionUrl).subscribe((response) => {
|
||||
expect(response).toBeTruthy();
|
||||
@ -205,12 +222,14 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
|
||||
httpRequest.flush('something');
|
||||
httpTestingController.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when no config is present', waitForAsync(() => {
|
||||
it('should not add an Authorization header when no config is present', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
|
||||
spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(false);
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
false
|
||||
);
|
||||
|
||||
httpClient.get(actionUrl).subscribe((response) => {
|
||||
expect(response).toBeTruthy();
|
||||
@ -222,22 +241,24 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
|
||||
httpRequest.flush('something');
|
||||
httpTestingController.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should not add an Authorization header when no configured route is matching the request', waitForAsync(() => {
|
||||
spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
|
||||
it('should not add an Authorization header when no configured route is matching the request', async () => {
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
true
|
||||
);
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
|
||||
spyOn(configurationService, 'getAllConfigurations').and.returnValue([
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{
|
||||
secureRoutes: [actionUrl],
|
||||
configId: 'configId1',
|
||||
},
|
||||
]);
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
closestMatchingRouteService,
|
||||
'getConfigIdForClosestMatchingRoute'
|
||||
).and.returnValue({
|
||||
).mockReturnValue({
|
||||
matchingRoute: null,
|
||||
matchingConfig: null,
|
||||
});
|
||||
@ -252,18 +273,22 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
|
||||
httpRequest.flush('something');
|
||||
httpTestingController.verify();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should add an Authorization header when multiple routes are configured and token is present', waitForAsync(() => {
|
||||
it('should add an Authorization header when multiple routes are configured and token is present', async () => {
|
||||
const actionUrl = `https://jsonplaceholder.typicode.com/`;
|
||||
const actionUrl2 = `https://some-other-url.com/`;
|
||||
|
||||
spyOn(configurationService, 'getAllConfigurations').and.returnValue([
|
||||
vi.spyOn(configurationService, 'getAllConfigurations').mockReturnValue([
|
||||
{ secureRoutes: [actionUrl, actionUrl2], configId: 'configId1' },
|
||||
]);
|
||||
|
||||
spyOn(authStateService, 'getAccessToken').and.returnValue('thisIsAToken');
|
||||
spyOn(configurationService, 'hasAtLeastOneConfig').and.returnValue(true);
|
||||
vi.spyOn(authStateService, 'getAccessToken').mockReturnValue(
|
||||
'thisIsAToken'
|
||||
);
|
||||
vi.spyOn(configurationService, 'hasAtLeastOneConfig').mockReturnValue(
|
||||
true
|
||||
);
|
||||
|
||||
httpClient.get(actionUrl).subscribe((response) => {
|
||||
expect(response).toBeTruthy();
|
||||
@ -284,6 +309,6 @@ describe(`AuthHttpInterceptor`, () => {
|
||||
httpRequest.flush('something');
|
||||
httpRequest2.flush('something');
|
||||
httpTestingController.verify();
|
||||
}));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { ClosestMatchingRouteService } from './closest-matching-route.service';
|
||||
|
||||
describe('ClosestMatchingRouteService', () => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { AbstractLoggerService } from './abstract-logger.service';
|
||||
import { ConsoleLoggerService } from './console-logger.service';
|
||||
import { LogLevel } from './log-level';
|
||||
@ -26,7 +27,7 @@ describe('Logger Service', () => {
|
||||
|
||||
describe('logError', () => {
|
||||
it('should not log error if loglevel is None', () => {
|
||||
const spy = spyOn(console, 'error');
|
||||
const spy = vi.spyOn(console, 'error');
|
||||
|
||||
loggerService.logError(
|
||||
{ configId: 'configId1', logLevel: LogLevel.None },
|
||||
@ -36,23 +37,25 @@ describe('Logger Service', () => {
|
||||
});
|
||||
|
||||
it('should log error as default if error is string', () => {
|
||||
const spy = spyOn(console, 'error');
|
||||
const spy = vi.spyOn(console, 'error');
|
||||
|
||||
loggerService.logError({ configId: 'configId1' }, 'some message');
|
||||
expect(spy).toHaveBeenCalledOnceWith('[ERROR] configId1 - some message');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[ERROR] configId1 - some message'
|
||||
);
|
||||
});
|
||||
|
||||
it('should log error as default if error is object', () => {
|
||||
const spy = spyOn(console, 'error');
|
||||
const spy = vi.spyOn(console, 'error');
|
||||
|
||||
loggerService.logError({ configId: 'configId1' }, { some: 'message' });
|
||||
expect(spy).toHaveBeenCalledOnceWith(
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[ERROR] configId1 - {"some":"message"}'
|
||||
);
|
||||
});
|
||||
|
||||
it('should always log error with args', () => {
|
||||
const spy = spyOn(console, 'error');
|
||||
const spy = vi.spyOn(console, 'error');
|
||||
|
||||
loggerService.logError(
|
||||
{ configId: 'configId1' },
|
||||
@ -60,7 +63,7 @@ describe('Logger Service', () => {
|
||||
'arg1',
|
||||
'arg2'
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith(
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[ERROR] configId1 - some message',
|
||||
'arg1',
|
||||
'arg2'
|
||||
@ -70,7 +73,7 @@ describe('Logger Service', () => {
|
||||
|
||||
describe('logWarn', () => {
|
||||
it('should not log if no log level is set (null)', () => {
|
||||
const spy = spyOn(console, 'warn');
|
||||
const spy = vi.spyOn(console, 'warn');
|
||||
|
||||
loggerService.logWarning(
|
||||
{ configId: 'configId1', logLevel: undefined },
|
||||
@ -80,14 +83,14 @@ describe('Logger Service', () => {
|
||||
});
|
||||
|
||||
it('should not log if no config is given', () => {
|
||||
const spy = spyOn(console, 'warn');
|
||||
const spy = vi.spyOn(console, 'warn');
|
||||
|
||||
loggerService.logWarning({}, 'some message');
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not log if no log level is set (undefined)', () => {
|
||||
const spy = spyOn(console, 'warn');
|
||||
const spy = vi.spyOn(console, 'warn');
|
||||
|
||||
loggerService.logWarning({ configId: 'configId1' }, 'some message');
|
||||
|
||||
@ -95,7 +98,7 @@ describe('Logger Service', () => {
|
||||
});
|
||||
|
||||
it('should not log if log level is turned off', () => {
|
||||
const spy = spyOn(console, 'warn');
|
||||
const spy = vi.spyOn(console, 'warn');
|
||||
|
||||
loggerService.logWarning(
|
||||
{ configId: 'configId1', logLevel: LogLevel.None },
|
||||
@ -105,29 +108,31 @@ describe('Logger Service', () => {
|
||||
});
|
||||
|
||||
it('should log warning when loglevel is Warn and message is string', () => {
|
||||
const spy = spyOn(console, 'warn');
|
||||
const spy = vi.spyOn(console, 'warn');
|
||||
|
||||
loggerService.logWarning(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Warn },
|
||||
'some message'
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith('[WARN] configId1 - some message');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[WARN] configId1 - some message'
|
||||
);
|
||||
});
|
||||
|
||||
it('should log warning when loglevel is Warn and message is object', () => {
|
||||
const spy = spyOn(console, 'warn');
|
||||
const spy = vi.spyOn(console, 'warn');
|
||||
|
||||
loggerService.logWarning(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Warn },
|
||||
{ some: 'message' }
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith(
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[WARN] configId1 - {"some":"message"}'
|
||||
);
|
||||
});
|
||||
|
||||
it('should log warning when loglevel is Warn with args', () => {
|
||||
const spy = spyOn(console, 'warn');
|
||||
const spy = vi.spyOn(console, 'warn');
|
||||
|
||||
loggerService.logWarning(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Warn },
|
||||
@ -135,7 +140,7 @@ describe('Logger Service', () => {
|
||||
'arg1',
|
||||
'arg2'
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith(
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[WARN] configId1 - some message',
|
||||
'arg1',
|
||||
'arg2'
|
||||
@ -143,17 +148,19 @@ describe('Logger Service', () => {
|
||||
});
|
||||
|
||||
it('should log warning when loglevel is Debug', () => {
|
||||
const spy = spyOn(console, 'warn');
|
||||
const spy = vi.spyOn(console, 'warn');
|
||||
|
||||
loggerService.logWarning(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Debug },
|
||||
'some message'
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith('[WARN] configId1 - some message');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[WARN] configId1 - some message'
|
||||
);
|
||||
});
|
||||
|
||||
it('should not log warning when loglevel is error', () => {
|
||||
const spy = spyOn(console, 'warn');
|
||||
const spy = vi.spyOn(console, 'warn');
|
||||
|
||||
loggerService.logWarning(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Error },
|
||||
@ -165,7 +172,7 @@ describe('Logger Service', () => {
|
||||
|
||||
describe('logDebug', () => {
|
||||
it('should not log if no log level is set (null)', () => {
|
||||
const spy = spyOn(console, 'debug');
|
||||
const spy = vi.spyOn(console, 'debug');
|
||||
|
||||
loggerService.logDebug(
|
||||
{ configId: 'configId1', logLevel: undefined },
|
||||
@ -175,14 +182,14 @@ describe('Logger Service', () => {
|
||||
});
|
||||
|
||||
it('should not log if no log level is set (undefined)', () => {
|
||||
const spy = spyOn(console, 'debug');
|
||||
const spy = vi.spyOn(console, 'debug');
|
||||
|
||||
loggerService.logDebug({ configId: 'configId1' }, 'some message');
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not log if log level is turned off', () => {
|
||||
const spy = spyOn(console, 'debug');
|
||||
const spy = vi.spyOn(console, 'debug');
|
||||
|
||||
loggerService.logDebug(
|
||||
{ configId: 'configId1', logLevel: LogLevel.None },
|
||||
@ -192,29 +199,31 @@ describe('Logger Service', () => {
|
||||
});
|
||||
|
||||
it('should log when loglevel is Debug and value is string', () => {
|
||||
const spy = spyOn(console, 'debug');
|
||||
const spy = vi.spyOn(console, 'debug');
|
||||
|
||||
loggerService.logDebug(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Debug },
|
||||
'some message'
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith('[DEBUG] configId1 - some message');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[DEBUG] configId1 - some message'
|
||||
);
|
||||
});
|
||||
|
||||
it('should log when loglevel is Debug and value is object', () => {
|
||||
const spy = spyOn(console, 'debug');
|
||||
const spy = vi.spyOn(console, 'debug');
|
||||
|
||||
loggerService.logDebug(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Debug },
|
||||
{ some: 'message' }
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith(
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[DEBUG] configId1 - {"some":"message"}'
|
||||
);
|
||||
});
|
||||
|
||||
it('should log when loglevel is Debug with args', () => {
|
||||
const spy = spyOn(console, 'debug');
|
||||
const spy = vi.spyOn(console, 'debug');
|
||||
|
||||
loggerService.logDebug(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Debug },
|
||||
@ -222,7 +231,7 @@ describe('Logger Service', () => {
|
||||
'arg1',
|
||||
'arg2'
|
||||
);
|
||||
expect(spy).toHaveBeenCalledOnceWith(
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'[DEBUG] configId1 - some message',
|
||||
'arg1',
|
||||
'arg2'
|
||||
@ -230,7 +239,7 @@ describe('Logger Service', () => {
|
||||
});
|
||||
|
||||
it('should not log when loglevel is Warn', () => {
|
||||
const spy = spyOn(console, 'debug');
|
||||
const spy = vi.spyOn(console, 'debug');
|
||||
|
||||
loggerService.logDebug(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Warn },
|
||||
@ -240,7 +249,7 @@ describe('Logger Service', () => {
|
||||
});
|
||||
|
||||
it('should not log when loglevel is error', () => {
|
||||
const spy = spyOn(console, 'debug');
|
||||
const spy = vi.spyOn(console, 'debug');
|
||||
|
||||
loggerService.logDebug(
|
||||
{ configId: 'configId1', logLevel: LogLevel.Error },
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { Injectable } from 'injection-js';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { injectAbstractType } from '../injection/inject';
|
||||
import { AbstractLoggerService } from './abstract-logger.service';
|
||||
import { LogLevel } from './log-level';
|
||||
|
||||
@Injectable()
|
||||
export class LoggerService {
|
||||
private readonly abstractLoggerService = inject(AbstractLoggerService);
|
||||
private readonly abstractLoggerService = injectAbstractType(
|
||||
AbstractLoggerService
|
||||
);
|
||||
|
||||
logError(
|
||||
configuration: OpenIdConfiguration,
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { LoginResponse } from './login-response';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import type { LoginResponse } from './login-response';
|
||||
import { LoginService } from './login.service';
|
||||
import { ParLoginService } from './par/par-login.service';
|
||||
import { PopUpLoginService } from './popup/popup-login.service';
|
||||
@ -48,8 +49,8 @@ describe('LoginService', () => {
|
||||
describe('login', () => {
|
||||
it('calls parLoginService loginPar if usePushedAuthorisationRequests is true', () => {
|
||||
const config = { usePushedAuthorisationRequests: true };
|
||||
const loginParSpy = spyOn(parLoginService, 'loginPar');
|
||||
const standardLoginSpy = spyOn(standardLoginService, 'loginStandard');
|
||||
const loginParSpy = vi.spyOn(parLoginService, 'loginPar');
|
||||
const standardLoginSpy = vi.spyOn(standardLoginService, 'loginStandard');
|
||||
|
||||
service.login(config);
|
||||
|
||||
@ -59,8 +60,8 @@ describe('LoginService', () => {
|
||||
|
||||
it('calls standardLoginService loginStandard if usePushedAuthorisationRequests is false', () => {
|
||||
const config = { usePushedAuthorisationRequests: false };
|
||||
const loginParSpy = spyOn(parLoginService, 'loginPar');
|
||||
const standardLoginSpy = spyOn(standardLoginService, 'loginStandard');
|
||||
const loginParSpy = vi.spyOn(parLoginService, 'loginPar');
|
||||
const standardLoginSpy = vi.spyOn(standardLoginService, 'loginStandard');
|
||||
|
||||
service.login(config);
|
||||
|
||||
@ -71,7 +72,7 @@ describe('LoginService', () => {
|
||||
it('stores the customParams to the storage if customParams are given', () => {
|
||||
// arrange
|
||||
const config = { usePushedAuthorisationRequests: false };
|
||||
const storagePersistenceServiceSpy = spyOn(
|
||||
const storagePersistenceServiceSpy = vi.spyOn(
|
||||
storagePersistenceService,
|
||||
'write'
|
||||
);
|
||||
@ -79,7 +80,7 @@ describe('LoginService', () => {
|
||||
|
||||
service.login(config, authOptions);
|
||||
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledOnceWith(
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageCustomParamsAuthRequest',
|
||||
{ custom: 'params' },
|
||||
config
|
||||
@ -89,8 +90,8 @@ describe('LoginService', () => {
|
||||
it("should throw error if configuration is null and doesn't call loginPar or loginStandard", () => {
|
||||
// arrange
|
||||
const config = null;
|
||||
const loginParSpy = spyOn(parLoginService, 'loginPar');
|
||||
const standardLoginSpy = spyOn(standardLoginService, 'loginStandard');
|
||||
const loginParSpy = vi.spyOn(parLoginService, 'loginPar');
|
||||
const standardLoginSpy = vi.spyOn(standardLoginService, 'loginStandard');
|
||||
const authOptions = { customParams: { custom: 'params' } };
|
||||
|
||||
// act
|
||||
@ -106,17 +107,15 @@ describe('LoginService', () => {
|
||||
});
|
||||
|
||||
describe('loginWithPopUp', () => {
|
||||
it('calls parLoginService loginWithPopUpPar if usePushedAuthorisationRequests is true', waitForAsync(() => {
|
||||
it('calls parLoginService loginWithPopUpPar if usePushedAuthorisationRequests is true', async () => {
|
||||
// arrange
|
||||
const config = { usePushedAuthorisationRequests: true };
|
||||
const loginWithPopUpPar = spyOn(
|
||||
parLoginService,
|
||||
'loginWithPopUpPar'
|
||||
).and.returnValue(of({} as LoginResponse));
|
||||
const loginWithPopUpStandardSpy = spyOn(
|
||||
popUpLoginService,
|
||||
'loginWithPopUpStandard'
|
||||
).and.returnValue(of({} as LoginResponse));
|
||||
const loginWithPopUpPar = vi
|
||||
.spyOn(parLoginService, 'loginWithPopUpPar')
|
||||
.mockReturnValue(of({} as LoginResponse));
|
||||
const loginWithPopUpStandardSpy = vi
|
||||
.spyOn(popUpLoginService, 'loginWithPopUpStandard')
|
||||
.mockReturnValue(of({} as LoginResponse));
|
||||
|
||||
// act
|
||||
service.loginWithPopUp(config, [config]).subscribe(() => {
|
||||
@ -124,19 +123,17 @@ describe('LoginService', () => {
|
||||
expect(loginWithPopUpPar).toHaveBeenCalledTimes(1);
|
||||
expect(loginWithPopUpStandardSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls standardLoginService loginstandard if usePushedAuthorisationRequests is false', waitForAsync(() => {
|
||||
it('calls standardLoginService loginstandard if usePushedAuthorisationRequests is false', async () => {
|
||||
// arrange
|
||||
const config = { usePushedAuthorisationRequests: false };
|
||||
const loginWithPopUpPar = spyOn(
|
||||
parLoginService,
|
||||
'loginWithPopUpPar'
|
||||
).and.returnValue(of({} as LoginResponse));
|
||||
const loginWithPopUpStandardSpy = spyOn(
|
||||
popUpLoginService,
|
||||
'loginWithPopUpStandard'
|
||||
).and.returnValue(of({} as LoginResponse));
|
||||
const loginWithPopUpPar = vi
|
||||
.spyOn(parLoginService, 'loginWithPopUpPar')
|
||||
.mockReturnValue(of({} as LoginResponse));
|
||||
const loginWithPopUpStandardSpy = vi
|
||||
.spyOn(popUpLoginService, 'loginWithPopUpStandard')
|
||||
.mockReturnValue(of({} as LoginResponse));
|
||||
|
||||
// act
|
||||
service.loginWithPopUp(config, [config]).subscribe(() => {
|
||||
@ -144,46 +141,44 @@ describe('LoginService', () => {
|
||||
expect(loginWithPopUpPar).not.toHaveBeenCalled();
|
||||
expect(loginWithPopUpStandardSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('stores the customParams to the storage if customParams are given', waitForAsync(() => {
|
||||
it('stores the customParams to the storage if customParams are given', async () => {
|
||||
// arrange
|
||||
const config = { usePushedAuthorisationRequests: false };
|
||||
const storagePersistenceServiceSpy = spyOn(
|
||||
const storagePersistenceServiceSpy = vi.spyOn(
|
||||
storagePersistenceService,
|
||||
'write'
|
||||
);
|
||||
const authOptions = { customParams: { custom: 'params' } };
|
||||
|
||||
spyOn(popUpLoginService, 'loginWithPopUpStandard').and.returnValue(
|
||||
vi.spyOn(popUpLoginService, 'loginWithPopUpStandard').mockReturnValue(
|
||||
of({} as LoginResponse)
|
||||
);
|
||||
|
||||
// act
|
||||
service.loginWithPopUp(config, [config], authOptions).subscribe(() => {
|
||||
// assert
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledOnceWith(
|
||||
expect(storagePersistenceServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'storageCustomParamsAuthRequest',
|
||||
{ custom: 'params' },
|
||||
config
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns error if there is already a popup open', () => {
|
||||
// arrange
|
||||
const config = { usePushedAuthorisationRequests: false };
|
||||
const authOptions = { customParams: { custom: 'params' } };
|
||||
const loginWithPopUpPar = spyOn(
|
||||
parLoginService,
|
||||
'loginWithPopUpPar'
|
||||
).and.returnValue(of({} as LoginResponse));
|
||||
const loginWithPopUpStandardSpy = spyOn(
|
||||
popUpLoginService,
|
||||
'loginWithPopUpStandard'
|
||||
).and.returnValue(of({} as LoginResponse));
|
||||
const loginWithPopUpPar = vi
|
||||
.spyOn(parLoginService, 'loginWithPopUpPar')
|
||||
.mockReturnValue(of({} as LoginResponse));
|
||||
const loginWithPopUpStandardSpy = vi
|
||||
.spyOn(popUpLoginService, 'loginWithPopUpStandard')
|
||||
.mockReturnValue(of({} as LoginResponse));
|
||||
|
||||
spyOn(popUpService, 'isCurrentlyInPopup').and.returnValue(true);
|
||||
vi.spyOn(popUpService, 'isCurrentlyInPopup').mockReturnValue(true);
|
||||
|
||||
// act
|
||||
service
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { AuthOptions } from '../auth-options';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of } from 'rxjs';
|
||||
import type { AuthOptions } from '../auth-options';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { LoginResponse } from './login-response';
|
||||
import type { LoginResponse } from './login-response';
|
||||
import { ParLoginService } from './par/par-login.service';
|
||||
import { PopUpLoginService } from './popup/popup-login.service';
|
||||
import { PopupOptions } from './popup/popup-options';
|
||||
import type { PopupOptions } from './popup/popup-options';
|
||||
import { PopUpService } from './popup/popup.service';
|
||||
import { StandardLoginService } from './standard/standard-login.service';
|
||||
|
||||
@ -45,12 +45,9 @@ export class LoginService {
|
||||
}
|
||||
|
||||
if (usePushedAuthorisationRequests) {
|
||||
return this.parLoginService.loginPar(configuration, authOptions);
|
||||
this.parLoginService.loginPar(configuration, authOptions);
|
||||
} else {
|
||||
return this.standardLoginService.loginStandard(
|
||||
configuration,
|
||||
authOptions
|
||||
);
|
||||
this.standardLoginService.loginStandard(configuration, authOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,18 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { CheckAuthService } from '../../auth-state/check-auth.service';
|
||||
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { RedirectService } from '../../utils/redirect/redirect.service';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { LoginResponse } from '../login-response';
|
||||
import { PopupResult } from '../popup/popup-result';
|
||||
import type { LoginResponse } from '../login-response';
|
||||
import type { PopupResult } from '../popup/popup-result';
|
||||
import { PopUpService } from '../popup/popup.service';
|
||||
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
|
||||
import { ParLoginService } from './par-login.service';
|
||||
import { ParResponse } from './par-response';
|
||||
import type { ParResponse } from './par-response';
|
||||
import { ParService } from './par.service';
|
||||
|
||||
describe('ParLoginService', () => {
|
||||
@ -60,33 +61,33 @@ describe('ParLoginService', () => {
|
||||
});
|
||||
|
||||
describe('loginPar', () => {
|
||||
it('does nothing if it has an invalid response type', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('does nothing if it has an invalid response type', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(false);
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
).mockReturnValue(false);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
const result = service.loginPar({});
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls parService.postParRequest without custom params when no custom params are passed', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('calls parService.postParRequest without custom params when no custom params are passed', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
const spy = spyOn(parService, 'postParRequest').and.returnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
const spy = vi
|
||||
.spyOn(parService, 'postParRequest')
|
||||
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
|
||||
|
||||
const result = service.loginPar({
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
@ -95,69 +96,69 @@ describe('ParLoginService', () => {
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls parService.postParRequest with custom params when custom params are passed', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('calls parService.postParRequest with custom params when custom params are passed', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
const spy = spyOn(parService, 'postParRequest').and.returnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
const spy = vi
|
||||
.spyOn(parService, 'postParRequest')
|
||||
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
|
||||
|
||||
const result = service.loginPar(config, {
|
||||
customParams: { some: 'thing' },
|
||||
});
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(spy).toHaveBeenCalledOnceWith(config, {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
|
||||
customParams: { some: 'thing' },
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns undefined and logs error when no url could be created', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('returns undefined and logs error when no url could be created', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(parService, 'postParRequest').and.returnValue(
|
||||
vi.spyOn(parService, 'postParRequest').mockReturnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('');
|
||||
const spy = spyOn(loggerService, 'logError');
|
||||
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue('');
|
||||
const spy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
const result = service.loginPar(config);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls redirect service redirectTo when url could be created', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('calls redirect service redirectTo when url could be created', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
@ -165,42 +166,46 @@ describe('ParLoginService', () => {
|
||||
|
||||
const authOptions = {};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(parService, 'postParRequest').and.returnValue(
|
||||
vi.spyOn(parService, 'postParRequest').mockReturnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
|
||||
const spy = spyOn(redirectService, 'redirectTo');
|
||||
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
|
||||
'some-par-url'
|
||||
);
|
||||
const spy = vi.spyOn(redirectService, 'redirectTo');
|
||||
|
||||
service.loginPar(config, authOptions);
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('some-par-url');
|
||||
}));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-par-url');
|
||||
});
|
||||
|
||||
it('calls urlHandler when URL is passed', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('calls urlHandler when URL is passed', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(parService, 'postParRequest').and.returnValue(
|
||||
vi.spyOn(parService, 'postParRequest').mockReturnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
|
||||
const redirectToSpy = spyOn(redirectService, 'redirectTo');
|
||||
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
|
||||
'some-par-url'
|
||||
);
|
||||
const redirectToSpy = vi.spyOn(redirectService, 'redirectTo');
|
||||
const spy = jasmine.createSpy();
|
||||
const urlHandler = (url: any): void => {
|
||||
spy(url);
|
||||
@ -208,18 +213,18 @@ describe('ParLoginService', () => {
|
||||
|
||||
service.loginPar(config, { urlHandler });
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('some-par-url');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('some-par-url');
|
||||
expect(redirectToSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('loginWithPopUpPar', () => {
|
||||
it('does nothing if it has an invalid response type', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('does nothing if it has an invalid response type', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(false);
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
).mockReturnValue(false);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
const config = {};
|
||||
const allConfigs = [config];
|
||||
|
||||
@ -229,27 +234,27 @@ describe('ParLoginService', () => {
|
||||
expect(err.message).toBe('Invalid response type!');
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls parService.postParRequest without custom params when no custom params are passed', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('calls parService.postParRequest without custom params when no custom params are passed', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
const allConfigs = [config];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
const spy = spyOn(parService, 'postParRequest').and.returnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
const spy = vi
|
||||
.spyOn(parService, 'postParRequest')
|
||||
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
|
||||
|
||||
service.loginWithPopUpPar(config, allConfigs).subscribe({
|
||||
error: (err) => {
|
||||
@ -259,27 +264,27 @@ describe('ParLoginService', () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls parService.postParRequest with custom params when custom params are passed', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('calls parService.postParRequest with custom params when custom params are passed', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
const allConfigs = [config];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
const spy = spyOn(parService, 'postParRequest').and.returnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
const spy = vi
|
||||
.spyOn(parService, 'postParRequest')
|
||||
.mockReturnValue(of({ requestUri: 'requestUri' } as ParResponse));
|
||||
|
||||
service
|
||||
.loginWithPopUpPar(config, allConfigs, {
|
||||
@ -287,7 +292,7 @@ describe('ParLoginService', () => {
|
||||
})
|
||||
.subscribe({
|
||||
error: (err) => {
|
||||
expect(spy).toHaveBeenCalledOnceWith(config, {
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
|
||||
customParams: { some: 'thing' },
|
||||
});
|
||||
expect(err.message).toBe(
|
||||
@ -295,29 +300,29 @@ describe('ParLoginService', () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns undefined and logs error when no URL could be created', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('returns undefined and logs error when no URL could be created', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
const allConfigs = [config];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(parService, 'postParRequest').and.returnValue(
|
||||
vi.spyOn(parService, 'postParRequest').mockReturnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('');
|
||||
const spy = spyOn(loggerService, 'logError');
|
||||
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue('');
|
||||
const spy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
service
|
||||
.loginWithPopUpPar(config, allConfigs, {
|
||||
@ -331,46 +336,52 @@ describe('ParLoginService', () => {
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls popupService openPopUp when URL could be created', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('calls popupService openPopUp when URL could be created', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
const allConfigs = [config];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(parService, 'postParRequest').and.returnValue(
|
||||
vi.spyOn(parService, 'postParRequest').mockReturnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
|
||||
spyOn(checkAuthService, 'checkAuth').and.returnValue(
|
||||
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
|
||||
'some-par-url'
|
||||
);
|
||||
vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue(
|
||||
of({} as LoginResponse)
|
||||
);
|
||||
spyOnProperty(popupService, 'result$').and.returnValue(
|
||||
vi.spyOnProperty(popupService, 'result$').mockReturnValue(
|
||||
of({} as PopupResult)
|
||||
);
|
||||
const spy = spyOn(popupService, 'openPopUp');
|
||||
const spy = vi.spyOn(popupService, 'openPopUp');
|
||||
|
||||
service.loginWithPopUpPar(config, allConfigs).subscribe(() => {
|
||||
expect(spy).toHaveBeenCalledOnceWith('some-par-url', undefined, config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-par-url',
|
||||
undefined,
|
||||
config
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns correct properties if URL is received', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('returns correct properties if URL is received', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
@ -378,34 +389,40 @@ describe('ParLoginService', () => {
|
||||
};
|
||||
const allConfigs = [config];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(parService, 'postParRequest').and.returnValue(
|
||||
vi.spyOn(parService, 'postParRequest').mockReturnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
|
||||
|
||||
const checkAuthSpy = spyOn(checkAuthService, 'checkAuth').and.returnValue(
|
||||
of({
|
||||
isAuthenticated: true,
|
||||
configId: 'configId1',
|
||||
idToken: '',
|
||||
userData: { any: 'userData' },
|
||||
accessToken: 'anyAccessToken',
|
||||
})
|
||||
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
|
||||
'some-par-url'
|
||||
);
|
||||
|
||||
const checkAuthSpy = vi
|
||||
.spyOn(checkAuthService, 'checkAuth')
|
||||
.mockReturnValue(
|
||||
of({
|
||||
isAuthenticated: true,
|
||||
configId: 'configId1',
|
||||
idToken: '',
|
||||
userData: { any: 'userData' },
|
||||
accessToken: 'anyAccessToken',
|
||||
})
|
||||
);
|
||||
const popupResult: PopupResult = {
|
||||
userClosed: false,
|
||||
receivedUrl: 'someUrl',
|
||||
};
|
||||
|
||||
spyOnProperty(popupService, 'result$').and.returnValue(of(popupResult));
|
||||
vi.spyOnProperty(popupService, 'result$').mockReturnValue(
|
||||
of(popupResult)
|
||||
);
|
||||
|
||||
service.loginWithPopUpPar(config, allConfigs).subscribe((result) => {
|
||||
expect(checkAuthSpy).toHaveBeenCalledOnceWith(
|
||||
expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
allConfigs,
|
||||
'someUrl'
|
||||
@ -419,13 +436,13 @@ describe('ParLoginService', () => {
|
||||
accessToken: 'anyAccessToken',
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns correct properties if popup was closed by user', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('returns correct properties if popup was closed by user', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
).mockReturnValue(true);
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
@ -433,20 +450,24 @@ describe('ParLoginService', () => {
|
||||
};
|
||||
const allConfigs = [config];
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
).mockReturnValue(of({}));
|
||||
|
||||
spyOn(parService, 'postParRequest').and.returnValue(
|
||||
vi.spyOn(parService, 'postParRequest').mockReturnValue(
|
||||
of({ requestUri: 'requestUri' } as ParResponse)
|
||||
);
|
||||
spyOn(urlService, 'getAuthorizeParUrl').and.returnValue('some-par-url');
|
||||
vi.spyOn(urlService, 'getAuthorizeParUrl').mockReturnValue(
|
||||
'some-par-url'
|
||||
);
|
||||
|
||||
const checkAuthSpy = spyOn(checkAuthService, 'checkAuth');
|
||||
const checkAuthSpy = vi.spyOn(checkAuthService, 'checkAuth');
|
||||
const popupResult = { userClosed: true } as PopupResult;
|
||||
|
||||
spyOnProperty(popupService, 'result$').and.returnValue(of(popupResult));
|
||||
vi.spyOnProperty(popupService, 'result$').mockReturnValue(
|
||||
of(popupResult)
|
||||
);
|
||||
|
||||
service.loginWithPopUpPar(config, allConfigs).subscribe((result) => {
|
||||
expect(checkAuthSpy).not.toHaveBeenCalled();
|
||||
@ -459,6 +480,6 @@ describe('ParLoginService', () => {
|
||||
accessToken: '',
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,19 +1,19 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { switchMap, take } from 'rxjs/operators';
|
||||
import { AuthOptions } from '../../auth-options';
|
||||
import type { AuthOptions } from '../../auth-options';
|
||||
import { CheckAuthService } from '../../auth-state/check-auth.service';
|
||||
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { RedirectService } from '../../utils/redirect/redirect.service';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { LoginResponse } from '../login-response';
|
||||
import { PopupOptions } from '../popup/popup-options';
|
||||
import { PopupResult } from '../popup/popup-result';
|
||||
import type { LoginResponse } from '../login-response';
|
||||
import type { PopupOptions } from '../popup/popup-options';
|
||||
import type { PopupResult } from '../popup/popup-result';
|
||||
import { PopUpService } from '../popup/popup.service';
|
||||
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
|
||||
import { ParResponse } from './par-response';
|
||||
import type { ParResponse } from './par-response';
|
||||
import { ParService } from './par.service';
|
||||
|
||||
@Injectable()
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { createRetriableStream } from '../../../test/create-retriable-stream.helper';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../../api/data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { createRetriableStream } from '../../testing/create-retriable-stream.helper';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { ParService } from './par.service';
|
||||
|
||||
@ -40,13 +41,15 @@ describe('ParService', () => {
|
||||
});
|
||||
|
||||
describe('postParRequest', () => {
|
||||
it('throws error if authWellKnownEndPoints does not exist in storage', waitForAsync(() => {
|
||||
spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
|
||||
it('throws error if authWellKnownEndPoints does not exist in storage', async () => {
|
||||
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
|
||||
of(null)
|
||||
);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue(null);
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => null
|
||||
);
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toBe(
|
||||
@ -54,15 +57,17 @@ describe('ParService', () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws error if par endpoint does not exist in storage', waitForAsync(() => {
|
||||
spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
|
||||
it('throws error if par endpoint does not exist in storage', async () => {
|
||||
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
|
||||
of(null)
|
||||
);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ some: 'thing' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ some: 'thing' })
|
||||
);
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toBe(
|
||||
@ -70,77 +75,87 @@ describe('ParService', () => {
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls data service with correct params', waitForAsync(() => {
|
||||
spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
|
||||
it('calls data service with correct params', async () => {
|
||||
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
|
||||
of('some-url123')
|
||||
);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ parEndpoint: 'parEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ parEndpoint: 'parEndpoint' })
|
||||
);
|
||||
|
||||
const dataServiceSpy = spyOn(dataService, 'post').and.returnValue(of({}));
|
||||
const dataServiceSpy = vi
|
||||
.spyOn(dataService, 'post')
|
||||
.mockReturnValue(of({}));
|
||||
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe(() => {
|
||||
expect(dataServiceSpy).toHaveBeenCalledOnceWith(
|
||||
expect(dataServiceSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'parEndpoint',
|
||||
'some-url123',
|
||||
{ configId: 'configId1' },
|
||||
jasmine.any(HttpHeaders)
|
||||
expect.any(HttpHeaders)
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('Gives back correct object properties', waitForAsync(() => {
|
||||
spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
|
||||
it('Gives back correct object properties', async () => {
|
||||
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
|
||||
of('some-url456')
|
||||
);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ parEndpoint: 'parEndpoint' });
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ parEndpoint: 'parEndpoint' })
|
||||
);
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
of({ expires_in: 123, request_uri: 'request_uri' })
|
||||
);
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe((result) => {
|
||||
expect(result).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('throws error if data service has got an error', waitForAsync(() => {
|
||||
spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
|
||||
it('throws error if data service has got an error', async () => {
|
||||
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
|
||||
of('some-url789')
|
||||
);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ parEndpoint: 'parEndpoint' });
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ parEndpoint: 'parEndpoint' })
|
||||
);
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
throwError(() => new Error('ERROR'))
|
||||
);
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
service.postParRequest({ configId: 'configId1' }).subscribe({
|
||||
error: (err) => {
|
||||
expect(err.message).toBe(
|
||||
'There was an error on ParService postParRequest'
|
||||
);
|
||||
expect(loggerSpy).toHaveBeenCalledOnceWith(
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'There was an error on ParService postParRequest',
|
||||
jasmine.any(Error)
|
||||
expect.any(Error)
|
||||
);
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry once', waitForAsync(() => {
|
||||
spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
|
||||
it('should retry once', async () => {
|
||||
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
|
||||
of('some-url456')
|
||||
);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ parEndpoint: 'parEndpoint' });
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ parEndpoint: 'parEndpoint' })
|
||||
);
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('ERROR')),
|
||||
of({ expires_in: 123, request_uri: 'request_uri' })
|
||||
@ -153,16 +168,18 @@ describe('ParService', () => {
|
||||
expect(res).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry twice', waitForAsync(() => {
|
||||
spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
|
||||
it('should retry twice', async () => {
|
||||
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
|
||||
of('some-url456')
|
||||
);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ parEndpoint: 'parEndpoint' });
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ parEndpoint: 'parEndpoint' })
|
||||
);
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('ERROR')),
|
||||
throwError(() => new Error('ERROR')),
|
||||
@ -176,16 +193,18 @@ describe('ParService', () => {
|
||||
expect(res).toEqual({ expiresIn: 123, requestUri: 'request_uri' });
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should fail after three tries', waitForAsync(() => {
|
||||
spyOn(urlService, 'createBodyForParCodeFlowRequest').and.returnValue(
|
||||
it('should fail after three tries', async () => {
|
||||
vi.spyOn(urlService, 'createBodyForParCodeFlowRequest').mockReturnValue(
|
||||
of('some-url456')
|
||||
);
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', { configId: 'configId1' })
|
||||
.and.returnValue({ parEndpoint: 'parEndpoint' });
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', { configId: 'configId1' }],
|
||||
() => ({ parEndpoint: 'parEndpoint' })
|
||||
);
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('ERROR')),
|
||||
throwError(() => new Error('ERROR')),
|
||||
@ -199,6 +218,6 @@ describe('ParService', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { CheckAuthService } from '../../auth-state/check-auth.service';
|
||||
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { LoginResponse } from '../login-response';
|
||||
import type { LoginResponse } from '../login-response';
|
||||
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
|
||||
import { PopUpLoginService } from './popup-login.service';
|
||||
import { PopupResult } from './popup-result';
|
||||
import type { PopupResult } from './popup-result';
|
||||
import { PopUpService } from './popup.service';
|
||||
|
||||
describe('PopUpLoginService', () => {
|
||||
@ -53,14 +54,14 @@ describe('PopUpLoginService', () => {
|
||||
});
|
||||
|
||||
describe('loginWithPopUpStandard', () => {
|
||||
it('does nothing if it has an invalid response type', waitForAsync(() => {
|
||||
it('does nothing if it has an invalid response type', async () => {
|
||||
const config = { responseType: 'stubValue' };
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(false);
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
).mockReturnValue(false);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
popUpLoginService.loginWithPopUpStandard(config, [config]).subscribe({
|
||||
error: (err) => {
|
||||
@ -68,27 +69,27 @@ describe('PopUpLoginService', () => {
|
||||
expect(err.message).toBe('Invalid response type!');
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls urlService.getAuthorizeUrl() if everything fits', waitForAsync(() => {
|
||||
it('calls urlService.getAuthorizeUrl() if everything fits', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
spyOnProperty(popupService, 'result$').and.returnValue(
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOnProperty(popupService, 'result$').mockReturnValue(
|
||||
of({} as PopupResult)
|
||||
);
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
|
||||
spyOn(checkAuthService, 'checkAuth').and.returnValue(
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue(
|
||||
of({} as LoginResponse)
|
||||
);
|
||||
|
||||
@ -97,74 +98,78 @@ describe('PopUpLoginService', () => {
|
||||
.subscribe(() => {
|
||||
expect(urlService.getAuthorizeUrl).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('opens popup if everything fits', waitForAsync(() => {
|
||||
it('opens popup if everything fits', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
|
||||
spyOnProperty(popupService, 'result$').and.returnValue(
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
vi.spyOnProperty(popupService, 'result$').mockReturnValue(
|
||||
of({} as PopupResult)
|
||||
);
|
||||
spyOn(checkAuthService, 'checkAuth').and.returnValue(
|
||||
vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue(
|
||||
of({} as LoginResponse)
|
||||
);
|
||||
const popupSpy = spyOn(popupService, 'openPopUp');
|
||||
const popupSpy = vi.spyOn(popupService, 'openPopUp');
|
||||
|
||||
popUpLoginService
|
||||
.loginWithPopUpStandard(config, [config])
|
||||
.subscribe(() => {
|
||||
expect(popupSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns three properties when popupservice received an url', waitForAsync(() => {
|
||||
it('returns three properties when popupservice received an url', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
|
||||
spyOn(popupService, 'openPopUp');
|
||||
const checkAuthSpy = spyOn(checkAuthService, 'checkAuth').and.returnValue(
|
||||
of({
|
||||
isAuthenticated: true,
|
||||
configId: 'configId1',
|
||||
idToken: '',
|
||||
userData: { any: 'userData' },
|
||||
accessToken: 'anyAccessToken',
|
||||
})
|
||||
);
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
vi.spyOn(popupService, 'openPopUp');
|
||||
const checkAuthSpy = vi
|
||||
.spyOn(checkAuthService, 'checkAuth')
|
||||
.mockReturnValue(
|
||||
of({
|
||||
isAuthenticated: true,
|
||||
configId: 'configId1',
|
||||
idToken: '',
|
||||
userData: { any: 'userData' },
|
||||
accessToken: 'anyAccessToken',
|
||||
})
|
||||
);
|
||||
const popupResult: PopupResult = {
|
||||
userClosed: false,
|
||||
receivedUrl: 'someUrl',
|
||||
};
|
||||
|
||||
spyOnProperty(popupService, 'result$').and.returnValue(of(popupResult));
|
||||
vi.spyOnProperty(popupService, 'result$').mockReturnValue(
|
||||
of(popupResult)
|
||||
);
|
||||
|
||||
popUpLoginService
|
||||
.loginWithPopUpStandard(config, [config])
|
||||
.subscribe((result) => {
|
||||
expect(checkAuthSpy).toHaveBeenCalledOnceWith(
|
||||
expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
[config],
|
||||
'someUrl'
|
||||
@ -178,31 +183,33 @@ describe('PopUpLoginService', () => {
|
||||
accessToken: 'anyAccessToken',
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('returns two properties if popup was closed by user', waitForAsync(() => {
|
||||
it('returns two properties if popup was closed by user', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
configId: 'configId1',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
|
||||
spyOn(popupService, 'openPopUp');
|
||||
const checkAuthSpy = spyOn(checkAuthService, 'checkAuth').and.returnValue(
|
||||
of({} as LoginResponse)
|
||||
);
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
vi.spyOn(popupService, 'openPopUp');
|
||||
const checkAuthSpy = vi
|
||||
.spyOn(checkAuthService, 'checkAuth')
|
||||
.mockReturnValue(of({} as LoginResponse));
|
||||
const popupResult = { userClosed: true } as PopupResult;
|
||||
|
||||
spyOnProperty(popupService, 'result$').and.returnValue(of(popupResult));
|
||||
vi.spyOnProperty(popupService, 'result$').mockReturnValue(
|
||||
of(popupResult)
|
||||
);
|
||||
|
||||
popUpLoginService
|
||||
.loginWithPopUpStandard(config, [config])
|
||||
@ -217,6 +224,6 @@ describe('PopUpLoginService', () => {
|
||||
accessToken: '',
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { switchMap, take, tap } from 'rxjs/operators';
|
||||
import { AuthOptions } from '../../auth-options';
|
||||
import type { AuthOptions } from '../../auth-options';
|
||||
import { CheckAuthService } from '../../auth-state/check-auth.service';
|
||||
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { LoginResponse } from '../login-response';
|
||||
import type { LoginResponse } from '../login-response';
|
||||
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
|
||||
import { PopupOptions } from './popup-options';
|
||||
import { PopupResult } from './popup-result';
|
||||
import type { PopupOptions } from './popup-options';
|
||||
import type { PopupResult } from './popup-result';
|
||||
import { PopUpService } from './popup.service';
|
||||
|
||||
@Injectable()
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { TestBed, fakeAsync, tick } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import { PopupResult } from './popup-result';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import type { PopupResult } from './popup-result';
|
||||
import { PopUpService } from './popup.service';
|
||||
|
||||
describe('PopUpService', () => {
|
||||
@ -18,9 +19,6 @@ describe('PopUpService', () => {
|
||||
mockProvider(LoggerService),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
storagePersistenceService = TestBed.inject(StoragePersistenceService);
|
||||
loggerService = TestBed.inject(LoggerService);
|
||||
popUpService = TestBed.inject(PopUpService);
|
||||
@ -51,13 +49,13 @@ describe('PopUpService', () => {
|
||||
describe('isCurrentlyInPopup', () => {
|
||||
it('returns false if can not access Session Storage', () => {
|
||||
// arrange
|
||||
spyOn(popUpService as any, 'canAccessSessionStorage').and.returnValue(
|
||||
vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue(
|
||||
false
|
||||
);
|
||||
spyOnProperty(popUpService as any, 'windowInternal').and.returnValue({
|
||||
vi.spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({
|
||||
opener: {} as Window,
|
||||
});
|
||||
spyOn(storagePersistenceService, 'read').and.returnValue({
|
||||
vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
|
||||
popupauth: true,
|
||||
});
|
||||
const config = {} as OpenIdConfiguration;
|
||||
@ -71,10 +69,10 @@ describe('PopUpService', () => {
|
||||
|
||||
it('returns false if window has no opener', () => {
|
||||
// arrange
|
||||
spyOn(popUpService as any, 'canAccessSessionStorage').and.returnValue(
|
||||
vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue(
|
||||
true
|
||||
);
|
||||
spyOn(storagePersistenceService, 'read').and.returnValue({
|
||||
vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
|
||||
popupauth: true,
|
||||
});
|
||||
const config = {} as OpenIdConfiguration;
|
||||
@ -88,13 +86,13 @@ describe('PopUpService', () => {
|
||||
|
||||
it('returns true if isCurrentlyInPopup', () => {
|
||||
// arrange
|
||||
spyOn(popUpService as any, 'canAccessSessionStorage').and.returnValue(
|
||||
vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue(
|
||||
true
|
||||
);
|
||||
spyOnProperty(popUpService as any, 'windowInternal').and.returnValue({
|
||||
vi.spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({
|
||||
opener: {} as Window,
|
||||
});
|
||||
spyOn(storagePersistenceService, 'read').and.returnValue({
|
||||
vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
|
||||
popupauth: true,
|
||||
});
|
||||
const config = {} as OpenIdConfiguration;
|
||||
@ -108,7 +106,7 @@ describe('PopUpService', () => {
|
||||
});
|
||||
|
||||
describe('result$', () => {
|
||||
it('emits when internal subject is called', waitForAsync(() => {
|
||||
it('emits when internal subject is called', async () => {
|
||||
const popupResult: PopupResult = {
|
||||
userClosed: false,
|
||||
receivedUrl: 'some-url1111',
|
||||
@ -119,62 +117,62 @@ describe('PopUpService', () => {
|
||||
});
|
||||
|
||||
(popUpService as any).resultInternal$.next(popupResult);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('openPopup', () => {
|
||||
it('popup opens with parameters and default options', waitForAsync(() => {
|
||||
it('popup opens with parameters and default options', async () => {
|
||||
// arrange
|
||||
const popupSpy = spyOn(window, 'open').and.callFake(
|
||||
const popupSpy = vi.spyOn(window, 'open').and.callFake(
|
||||
() =>
|
||||
({
|
||||
closed: true,
|
||||
close: () => undefined,
|
||||
} as Window)
|
||||
}) as Window
|
||||
);
|
||||
|
||||
// act
|
||||
popUpService.openPopUp('url', {}, { configId: 'configId1' });
|
||||
|
||||
// assert
|
||||
expect(popupSpy).toHaveBeenCalledOnceWith(
|
||||
expect(popupSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'url',
|
||||
'_blank',
|
||||
jasmine.any(String)
|
||||
expect.any(String)
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
it('popup opens with parameters and passed options', waitForAsync(() => {
|
||||
it('popup opens with parameters and passed options', async () => {
|
||||
// arrange
|
||||
const popupSpy = spyOn(window, 'open').and.callFake(
|
||||
const popupSpy = vi.spyOn(window, 'open').and.callFake(
|
||||
() =>
|
||||
({
|
||||
closed: true,
|
||||
close: () => undefined,
|
||||
} as Window)
|
||||
}) as Window
|
||||
);
|
||||
|
||||
// act
|
||||
popUpService.openPopUp('url', { width: 100 }, { configId: 'configId1' });
|
||||
|
||||
// assert
|
||||
expect(popupSpy).toHaveBeenCalledOnceWith(
|
||||
expect(popupSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'url',
|
||||
'_blank',
|
||||
jasmine.any(String)
|
||||
expect.any(String)
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
it('logs error and return if popup could not be opened', () => {
|
||||
// arrange
|
||||
spyOn(window, 'open').and.callFake(() => null);
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
vi.spyOn(window, 'open').mockImplementation(() => null);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
// act
|
||||
popUpService.openPopUp('url', { width: 100 }, { configId: 'configId1' });
|
||||
|
||||
// assert
|
||||
expect(loggerSpy).toHaveBeenCalledOnceWith(
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ configId: 'configId1' },
|
||||
'Could not open popup'
|
||||
);
|
||||
@ -191,21 +189,21 @@ describe('PopUpService', () => {
|
||||
close: () => undefined,
|
||||
} as Window;
|
||||
|
||||
spyOn(window, 'open').and.returnValue(popup);
|
||||
vi.spyOn(window, 'open').mockReturnValue(popup);
|
||||
|
||||
cleanUpSpy = spyOn(popUpService as any, 'cleanUp').and.callThrough();
|
||||
cleanUpSpy = vi.spyOn(popUpService as any, 'cleanUp')();
|
||||
|
||||
popupResult = {} as PopupResult;
|
||||
|
||||
popUpService.result$.subscribe((result) => (popupResult = result));
|
||||
});
|
||||
|
||||
it('message received with data', fakeAsync(() => {
|
||||
it('message received with data', async () => {
|
||||
let listener: (event: MessageEvent) => void = () => {
|
||||
return;
|
||||
};
|
||||
|
||||
spyOn(window, 'addEventListener').and.callFake(
|
||||
vi.spyOn(window, 'addEventListener').and.callFake(
|
||||
(_: any, func: any) => (listener = func)
|
||||
);
|
||||
|
||||
@ -222,20 +220,20 @@ describe('PopUpService', () => {
|
||||
userClosed: false,
|
||||
receivedUrl: 'some-url1111',
|
||||
});
|
||||
expect(cleanUpSpy).toHaveBeenCalledOnceWith(listener, {
|
||||
expect(cleanUpSpy).toHaveBeenCalledExactlyOnceWith(listener, {
|
||||
configId: 'configId1',
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('message received without data does return but cleanup does not throw event', fakeAsync(() => {
|
||||
it('message received without data does return but cleanup does not throw event', async () => {
|
||||
let listener: (event: MessageEvent) => void = () => {
|
||||
return;
|
||||
};
|
||||
|
||||
spyOn(window, 'addEventListener').and.callFake(
|
||||
vi.spyOn(window, 'addEventListener').and.callFake(
|
||||
(_: any, func: any) => (listener = func)
|
||||
);
|
||||
const nextSpy = spyOn((popUpService as any).resultInternal$, 'next');
|
||||
const nextSpy = vi.spyOn((popUpService as any).resultInternal$, 'next');
|
||||
|
||||
popUpService.openPopUp('url', {}, { configId: 'configId1' });
|
||||
|
||||
@ -249,9 +247,9 @@ describe('PopUpService', () => {
|
||||
expect(popupResult).toEqual({} as PopupResult);
|
||||
expect(cleanUpSpy).toHaveBeenCalled();
|
||||
expect(nextSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('user closed', fakeAsync(() => {
|
||||
it('user closed', async () => {
|
||||
popUpService.openPopUp('url', undefined, { configId: 'configId1' });
|
||||
|
||||
expect(popupResult).toEqual({} as PopupResult);
|
||||
@ -266,48 +264,48 @@ describe('PopUpService', () => {
|
||||
receivedUrl: '',
|
||||
} as PopupResult);
|
||||
expect(cleanUpSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('sendMessageToMainWindow', () => {
|
||||
it('does nothing if window.opener is null', waitForAsync(() => {
|
||||
it('does nothing if window.opener is null', async () => {
|
||||
// arrange
|
||||
spyOnProperty(window, 'opener').and.returnValue(null);
|
||||
vi.spyOnProperty(window, 'opener').mockReturnValue(null);
|
||||
|
||||
const sendMessageSpy = spyOn(popUpService as any, 'sendMessage');
|
||||
const sendMessageSpy = vi.spyOn(popUpService as any, 'sendMessage');
|
||||
|
||||
// act
|
||||
popUpService.sendMessageToMainWindow('', {});
|
||||
|
||||
// assert
|
||||
expect(sendMessageSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls postMessage when window opener is given', waitForAsync(() => {
|
||||
it('calls postMessage when window opener is given', async () => {
|
||||
// arrange
|
||||
spyOnProperty(window, 'opener').and.returnValue({
|
||||
vi.spyOnProperty(window, 'opener').mockReturnValue({
|
||||
postMessage: () => undefined,
|
||||
});
|
||||
const sendMessageSpy = spyOn(window.opener, 'postMessage');
|
||||
const sendMessageSpy = vi.spyOn(window.opener, 'postMessage');
|
||||
|
||||
// act
|
||||
popUpService.sendMessageToMainWindow('someUrl', {});
|
||||
|
||||
// assert
|
||||
expect(sendMessageSpy).toHaveBeenCalledOnceWith(
|
||||
expect(sendMessageSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'someUrl',
|
||||
jasmine.any(String)
|
||||
expect.any(String)
|
||||
);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('cleanUp', () => {
|
||||
it('calls removeEventListener on window with correct params', waitForAsync(() => {
|
||||
it('calls removeEventListener on window with correct params', async () => {
|
||||
// arrange
|
||||
const spy = spyOn(window, 'removeEventListener').and.callFake(
|
||||
() => undefined
|
||||
);
|
||||
const spy = vi
|
||||
.spyOn(window, 'removeEventListener')
|
||||
.mockImplementation(() => undefined);
|
||||
const listener: any = null;
|
||||
|
||||
// act
|
||||
@ -315,29 +313,29 @@ describe('PopUpService', () => {
|
||||
|
||||
// assert
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
expect(spy).toHaveBeenCalledOnceWith('message', listener, false);
|
||||
}));
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('message', listener, false);
|
||||
});
|
||||
|
||||
it('removes popup from sessionstorage, closes and nulls when popup is opened', waitForAsync(() => {
|
||||
it('removes popup from sessionstorage, closes and nulls when popup is opened', async () => {
|
||||
// arrange
|
||||
const popupMock = {
|
||||
anyThing: 'truthy',
|
||||
sessionStorage: mockStorage,
|
||||
close: (): void => undefined,
|
||||
};
|
||||
const removeItemSpy = spyOn(storagePersistenceService, 'remove');
|
||||
const closeSpy = spyOn(popupMock, 'close');
|
||||
const removeItemSpy = vi.spyOn(storagePersistenceService, 'remove');
|
||||
const closeSpy = vi.spyOn(popupMock, 'close');
|
||||
|
||||
// act
|
||||
(popUpService as any).popUp = popupMock;
|
||||
(popUpService as any).cleanUp(null, { configId: 'configId1' });
|
||||
|
||||
// assert
|
||||
expect(removeItemSpy).toHaveBeenCalledOnceWith('popupauth', {
|
||||
expect(removeItemSpy).toHaveBeenCalledExactlyOnceWith('popupauth', {
|
||||
configId: 'configId1',
|
||||
});
|
||||
expect(closeSpy).toHaveBeenCalledTimes(1);
|
||||
expect((popUpService as any).popUp).toBeNull();
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { FlowHelper } from '../../utils/flowHelper/flow-helper.service';
|
||||
import { ResponseTypeValidationService } from './response-type-validation.service';
|
||||
|
||||
@ -32,7 +33,9 @@ describe('ResponseTypeValidationService', () => {
|
||||
|
||||
describe('hasConfigValidResponseType', () => {
|
||||
it('returns true if current configured flow is any implicit flow', () => {
|
||||
spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(true);
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
|
||||
true
|
||||
);
|
||||
|
||||
const result = responseTypeValidationService.hasConfigValidResponseType({
|
||||
configId: 'configId1',
|
||||
@ -42,8 +45,10 @@ describe('ResponseTypeValidationService', () => {
|
||||
});
|
||||
|
||||
it('returns true if current configured flow is code flow', () => {
|
||||
spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(false);
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(true);
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
|
||||
false
|
||||
);
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(true);
|
||||
|
||||
const result = responseTypeValidationService.hasConfigValidResponseType({
|
||||
configId: 'configId1',
|
||||
@ -53,8 +58,10 @@ describe('ResponseTypeValidationService', () => {
|
||||
});
|
||||
|
||||
it('returns false if current configured flow is neither code nor implicit flow', () => {
|
||||
spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').and.returnValue(false);
|
||||
spyOn(flowHelper, 'isCurrentFlowCodeFlow').and.returnValue(false);
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowAnyImplicitFlow').mockReturnValue(
|
||||
false
|
||||
);
|
||||
vi.spyOn(flowHelper, 'isCurrentFlowCodeFlow').mockReturnValue(false);
|
||||
|
||||
const result = responseTypeValidationService.hasConfigValidResponseType({
|
||||
configId: 'configId1',
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, fakeAsync, tick } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../../../test/auto-mock';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthWellKnownService } from '../../config/auth-well-known/auth-well-known.service';
|
||||
import { FlowsDataService } from '../../flows/flows-data.service';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { mockProvider } from '../../testing/mock';
|
||||
import { RedirectService } from '../../utils/redirect/redirect.service';
|
||||
import { UrlService } from '../../utils/url/url.service';
|
||||
import { ResponseTypeValidationService } from '../response-type-validation/response-type-validation.service';
|
||||
@ -51,12 +52,12 @@ describe('StandardLoginService', () => {
|
||||
});
|
||||
|
||||
describe('loginStandard', () => {
|
||||
it('does nothing if it has an invalid response type', waitForAsync(() => {
|
||||
spyOn(
|
||||
it('does nothing if it has an invalid response type', async () => {
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(false);
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
).mockReturnValue(false);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
const result = standardLoginService.loginStandard({
|
||||
configId: 'configId1',
|
||||
@ -64,95 +65,92 @@ describe('StandardLoginService', () => {
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls flowsDataService.setCodeFlowInProgress() if everything fits', waitForAsync(() => {
|
||||
it('calls flowsDataService.setCodeFlowInProgress() if everything fits', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
|
||||
const flowsDataSpy = spyOn(flowsDataService, 'setCodeFlowInProgress');
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
const flowsDataSpy = vi.spyOn(flowsDataService, 'setCodeFlowInProgress');
|
||||
|
||||
const result = standardLoginService.loginStandard(config);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls urlService.getAuthorizeUrl() if everything fits', waitForAsync(() => {
|
||||
it('calls urlService.getAuthorizeUrl() if everything fits', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
|
||||
const result = standardLoginService.loginStandard(config);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
}));
|
||||
});
|
||||
|
||||
it('redirects to URL with no URL handler', fakeAsync(() => {
|
||||
it('redirects to URL with no URL handler', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
|
||||
const redirectSpy = spyOn(
|
||||
redirectService,
|
||||
'redirectTo'
|
||||
).and.callThrough();
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
const redirectSpy = vi.spyOn(redirectService, 'redirectTo')();
|
||||
|
||||
standardLoginService.loginStandard(config);
|
||||
tick();
|
||||
expect(redirectSpy).toHaveBeenCalledOnceWith('someUrl');
|
||||
}));
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someUrl');
|
||||
});
|
||||
|
||||
it('redirects to URL with URL handler when urlHandler is given', fakeAsync(() => {
|
||||
it('redirects to URL with URL handler when urlHandler is given', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
|
||||
const redirectSpy = spyOn(redirectService, 'redirectTo').and.callFake(
|
||||
() => undefined
|
||||
);
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
const redirectSpy = vi
|
||||
.spyOn(redirectService, 'redirectTo')
|
||||
.mockImplementation(() => undefined);
|
||||
const spy = jasmine.createSpy();
|
||||
const urlHandler = (url: any): void => {
|
||||
spy(url);
|
||||
@ -160,94 +158,96 @@ describe('StandardLoginService', () => {
|
||||
|
||||
standardLoginService.loginStandard(config, { urlHandler });
|
||||
tick();
|
||||
expect(spy).toHaveBeenCalledOnceWith('someUrl');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('someUrl');
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls resetSilentRenewRunning', fakeAsync(() => {
|
||||
it('calls resetSilentRenewRunning', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of('someUrl'));
|
||||
const flowsDataSpy = spyOn(flowsDataService, 'resetSilentRenewRunning');
|
||||
).mockReturnValue(of({}));
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
|
||||
const flowsDataSpy = vi.spyOn(
|
||||
flowsDataService,
|
||||
'resetSilentRenewRunning'
|
||||
);
|
||||
|
||||
standardLoginService.loginStandard(config, {});
|
||||
tick();
|
||||
|
||||
expect(flowsDataSpy).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls getAuthorizeUrl with custom params if they are given as parameter', fakeAsync(() => {
|
||||
it('calls getAuthorizeUrl with custom params if they are given as parameter', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
const getAuthorizeUrlSpy = spyOn(
|
||||
urlService,
|
||||
'getAuthorizeUrl'
|
||||
).and.returnValue(of('someUrl'));
|
||||
const redirectSpy = spyOn(redirectService, 'redirectTo').and.callFake(
|
||||
() => undefined
|
||||
);
|
||||
).mockReturnValue(of({}));
|
||||
const getAuthorizeUrlSpy = vi
|
||||
.spyOn(urlService, 'getAuthorizeUrl')
|
||||
.mockReturnValue(of('someUrl'));
|
||||
const redirectSpy = vi
|
||||
.spyOn(redirectService, 'redirectTo')
|
||||
.mockImplementation(() => undefined);
|
||||
|
||||
standardLoginService.loginStandard(config, {
|
||||
customParams: { to: 'add', as: 'well' },
|
||||
});
|
||||
tick();
|
||||
expect(redirectSpy).toHaveBeenCalledOnceWith('someUrl');
|
||||
expect(getAuthorizeUrlSpy).toHaveBeenCalledOnceWith(config, {
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someUrl');
|
||||
expect(getAuthorizeUrlSpy).toHaveBeenCalledExactlyOnceWith(config, {
|
||||
customParams: { to: 'add', as: 'well' },
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('does nothing, logs only if getAuthorizeUrl returns falsy', fakeAsync(() => {
|
||||
it('does nothing, logs only if getAuthorizeUrl returns falsy', async () => {
|
||||
const config = {
|
||||
authWellknownEndpointUrl: 'authWellknownEndpoint',
|
||||
responseType: 'stubValue',
|
||||
};
|
||||
|
||||
spyOn(
|
||||
vi.spyOn(
|
||||
responseTypeValidationService,
|
||||
'hasConfigValidResponseType'
|
||||
).and.returnValue(true);
|
||||
spyOn(
|
||||
).mockReturnValue(true);
|
||||
vi.spyOn(
|
||||
authWellKnownService,
|
||||
'queryAndStoreAuthWellKnownEndPoints'
|
||||
).and.returnValue(of({}));
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
).mockReturnValue(of({}));
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
spyOn(urlService, 'getAuthorizeUrl').and.returnValue(of(''));
|
||||
const redirectSpy = spyOn(redirectService, 'redirectTo').and.callFake(
|
||||
() => undefined
|
||||
);
|
||||
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of(''));
|
||||
const redirectSpy = vi
|
||||
.spyOn(redirectService, 'redirectTo')
|
||||
.mockImplementation(() => undefined);
|
||||
|
||||
standardLoginService.loginStandard(config);
|
||||
tick();
|
||||
expect(loggerSpy).toHaveBeenCalledOnceWith(
|
||||
expect(loggerSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
config,
|
||||
'Could not create URL',
|
||||
''
|
||||
);
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import type { HttpHeaders } from '@ngify/http';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { createRetriableStream } from '../../test/create-retriable-stream.helper';
|
||||
import { vi } from 'vitest';
|
||||
import { DataService } from '../api/data.service';
|
||||
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
|
||||
import { CheckSessionService } from '../iframe/check-session.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
import { createRetriableStream } from '../testing/create-retriable-stream.helper';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { RedirectService } from '../utils/redirect/redirect.service';
|
||||
import { UrlService } from '../utils/url/url.service';
|
||||
import { LogoffRevocationService } from './logoff-revocation.service';
|
||||
@ -55,70 +56,70 @@ describe('Logout and Revoke Service', () => {
|
||||
it('uses token parameter if token as parameter is passed in the method', () => {
|
||||
// Arrange
|
||||
const paramToken = 'passedTokenAsParam';
|
||||
const revocationSpy = spyOn(
|
||||
const revocationSpy = vi.spyOn(
|
||||
urlService,
|
||||
'createRevocationEndpointBodyAccessToken'
|
||||
);
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(of(null));
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(of(null));
|
||||
|
||||
// Act
|
||||
service.revokeAccessToken(config, paramToken);
|
||||
// Assert
|
||||
expect(revocationSpy).toHaveBeenCalledOnceWith(paramToken, config);
|
||||
expect(revocationSpy).toHaveBeenCalledExactlyOnceWith(paramToken, config);
|
||||
});
|
||||
|
||||
it('uses token parameter from persistence if no param is provided', () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
const revocationSpy = spyOn(
|
||||
const revocationSpy = vi.spyOn(
|
||||
urlService,
|
||||
'createRevocationEndpointBodyAccessToken'
|
||||
);
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(of(null));
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(of(null));
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
service.revokeAccessToken(config);
|
||||
// Assert
|
||||
expect(revocationSpy).toHaveBeenCalledOnceWith(paramToken, config);
|
||||
expect(revocationSpy).toHaveBeenCalledExactlyOnceWith(paramToken, config);
|
||||
});
|
||||
|
||||
it('returns type observable', () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
spyOn(dataService, 'post').and.returnValue(of(null));
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(of(null));
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
const result = service.revokeAccessToken(config);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(jasmine.any(Observable));
|
||||
expect(result).toEqual(expect.any(Observable));
|
||||
});
|
||||
|
||||
it('loggs and returns unmodified response if request is positive', waitForAsync(() => {
|
||||
it('loggs and returns unmodified response if request is positive', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logDebug');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logDebug');
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(of({ data: 'anything' }));
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(of({ data: 'anything' }));
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
@ -127,20 +128,20 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(result).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('loggs error when request is negative', waitForAsync(() => {
|
||||
it('loggs error when request is negative', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
@ -151,20 +152,20 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry once', waitForAsync(() => {
|
||||
it('should retry once', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logDebug');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logDebug');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('Error')),
|
||||
of({ data: 'anything' })
|
||||
@ -179,20 +180,20 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry twice', waitForAsync(() => {
|
||||
it('should retry twice', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logDebug');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logDebug');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('Error')),
|
||||
throwError(() => new Error('Error')),
|
||||
@ -208,20 +209,20 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should fail after three tries', waitForAsync(() => {
|
||||
it('should fail after three tries', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getAccessToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getAccessToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('Error')),
|
||||
throwError(() => new Error('Error')),
|
||||
@ -236,76 +237,76 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('revokeRefreshToken', () => {
|
||||
it('uses refresh token parameter if token as parameter is passed in the method', () => {
|
||||
// Arrange
|
||||
const paramToken = 'passedTokenAsParam';
|
||||
const revocationSpy = spyOn(
|
||||
const revocationSpy = vi.spyOn(
|
||||
urlService,
|
||||
'createRevocationEndpointBodyRefreshToken'
|
||||
);
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(of(null));
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(of(null));
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
service.revokeRefreshToken(config, paramToken);
|
||||
// Assert
|
||||
expect(revocationSpy).toHaveBeenCalledOnceWith(paramToken, config);
|
||||
expect(revocationSpy).toHaveBeenCalledExactlyOnceWith(paramToken, config);
|
||||
});
|
||||
|
||||
it('uses refresh token parameter from persistence if no param is provided', () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
const config = { configId: 'configId1' };
|
||||
const revocationSpy = spyOn(
|
||||
const revocationSpy = vi.spyOn(
|
||||
urlService,
|
||||
'createRevocationEndpointBodyRefreshToken'
|
||||
);
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(of(null));
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(of(null));
|
||||
// Act
|
||||
service.revokeRefreshToken(config);
|
||||
// Assert
|
||||
expect(revocationSpy).toHaveBeenCalledOnceWith(paramToken, config);
|
||||
expect(revocationSpy).toHaveBeenCalledExactlyOnceWith(paramToken, config);
|
||||
});
|
||||
|
||||
it('returns type observable', () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
spyOn(dataService, 'post').and.returnValue(of(null));
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(of(null));
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
const result = service.revokeRefreshToken(config);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(jasmine.any(Observable));
|
||||
expect(result).toEqual(expect.any(Observable));
|
||||
});
|
||||
|
||||
it('loggs and returns unmodified response if request is positive', waitForAsync(() => {
|
||||
it('loggs and returns unmodified response if request is positive', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logDebug');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logDebug');
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(of({ data: 'anything' }));
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(of({ data: 'anything' }));
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
@ -314,20 +315,20 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(result).toEqual({ data: 'anything' });
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('loggs error when request is negative', waitForAsync(() => {
|
||||
it('loggs error when request is negative', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
@ -338,20 +339,20 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry once', waitForAsync(() => {
|
||||
it('should retry once', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logDebug');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logDebug');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('Error')),
|
||||
of({ data: 'anything' })
|
||||
@ -366,20 +367,20 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should retry twice', waitForAsync(() => {
|
||||
it('should retry twice', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logDebug');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logDebug');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('Error')),
|
||||
throwError(() => new Error('Error')),
|
||||
@ -395,20 +396,20 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('should fail after three tries', waitForAsync(() => {
|
||||
it('should fail after three tries', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
vi.spyOn(urlService, 'createRevocationEndpointBodyAccessToken');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(dataService, 'post').and.returnValue(
|
||||
vi.spyOn(dataService, 'post').mockReturnValue(
|
||||
createRetriableStream(
|
||||
throwError(() => new Error('Error')),
|
||||
throwError(() => new Error('Error')),
|
||||
@ -423,15 +424,15 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(loggerSpy).toHaveBeenCalled();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('logoff', () => {
|
||||
it('logs and returns if `endSessionUrl` is false', waitForAsync(() => {
|
||||
it('logs and returns if `endSessionUrl` is false', async () => {
|
||||
// Arrange
|
||||
spyOn(urlService, 'getEndSessionUrl').and.returnValue('');
|
||||
vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('');
|
||||
|
||||
const serverStateChangedSpy = spyOn(
|
||||
const serverStateChangedSpy = vi.spyOn(
|
||||
checkSessionService,
|
||||
'serverStateChanged'
|
||||
);
|
||||
@ -444,14 +445,14 @@ describe('Logout and Revoke Service', () => {
|
||||
result$.subscribe(() => {
|
||||
expect(serverStateChangedSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('logs and returns if `serverStateChanged` is true', waitForAsync(() => {
|
||||
it('logs and returns if `serverStateChanged` is true', async () => {
|
||||
// Arrange
|
||||
spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
|
||||
const redirectSpy = spyOn(redirectService, 'redirectTo');
|
||||
vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
|
||||
const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
|
||||
|
||||
spyOn(checkSessionService, 'serverStateChanged').and.returnValue(true);
|
||||
vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(true);
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
@ -461,22 +462,24 @@ describe('Logout and Revoke Service', () => {
|
||||
result$.subscribe(() => {
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls urlHandler if urlhandler is passed', waitForAsync(() => {
|
||||
it('calls urlHandler if urlhandler is passed', async () => {
|
||||
// Arrange
|
||||
spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
|
||||
vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
|
||||
const spy = jasmine.createSpy();
|
||||
const urlHandler = (url: string): void => {
|
||||
spy(url);
|
||||
};
|
||||
const redirectSpy = spyOn(redirectService, 'redirectTo');
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
|
||||
spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
|
||||
vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
@ -485,18 +488,20 @@ describe('Logout and Revoke Service', () => {
|
||||
// Assert
|
||||
result$.subscribe(() => {
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
expect(spy).toHaveBeenCalledOnceWith('someValue');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls redirect service if no logoutOptions are passed', waitForAsync(() => {
|
||||
it('calls redirect service if no logoutOptions are passed', async () => {
|
||||
// Arrange
|
||||
spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
|
||||
vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
|
||||
|
||||
const redirectSpy = spyOn(redirectService, 'redirectTo');
|
||||
const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
|
||||
|
||||
spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
|
||||
vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
@ -504,17 +509,19 @@ describe('Logout and Revoke Service', () => {
|
||||
|
||||
// Assert
|
||||
result$.subscribe(() => {
|
||||
expect(redirectSpy).toHaveBeenCalledOnceWith('someValue');
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls redirect service if logoutOptions are passed and method is GET', waitForAsync(() => {
|
||||
it('calls redirect service if logoutOptions are passed and method is GET', async () => {
|
||||
// Arrange
|
||||
spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
|
||||
vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
|
||||
|
||||
const redirectSpy = spyOn(redirectService, 'redirectTo');
|
||||
const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
|
||||
|
||||
spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
|
||||
vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
|
||||
false
|
||||
);
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
@ -522,28 +529,30 @@ describe('Logout and Revoke Service', () => {
|
||||
|
||||
// Assert
|
||||
result$.subscribe(() => {
|
||||
expect(redirectSpy).toHaveBeenCalledOnceWith('someValue');
|
||||
expect(redirectSpy).toHaveBeenCalledExactlyOnceWith('someValue');
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls dataservice post if logoutOptions are passed and method is POST', waitForAsync(() => {
|
||||
it('calls dataservice post if logoutOptions are passed and method is POST', async () => {
|
||||
// Arrange
|
||||
spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
|
||||
vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
|
||||
|
||||
const redirectSpy = spyOn(redirectService, 'redirectTo');
|
||||
const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
|
||||
|
||||
spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
|
||||
false
|
||||
);
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'id-token'
|
||||
);
|
||||
spyOn(urlService, 'getPostLogoutRedirectUrl').and.returnValue(
|
||||
vi.spyOn(urlService, 'getPostLogoutRedirectUrl').mockReturnValue(
|
||||
'post-logout-redirect-url'
|
||||
);
|
||||
spyOn(urlService, 'getEndSessionEndpoint').and.returnValue({
|
||||
vi.spyOn(urlService, 'getEndSessionEndpoint').mockReturnValue({
|
||||
url: 'some-url',
|
||||
existingParams: '',
|
||||
});
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(of(null));
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of(null));
|
||||
const config = { configId: 'configId1', clientId: 'clientId' };
|
||||
|
||||
// Act
|
||||
@ -554,7 +563,7 @@ describe('Logout and Revoke Service', () => {
|
||||
// Assert
|
||||
result$.subscribe(() => {
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
expect(postSpy).toHaveBeenCalledOnceWith(
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url',
|
||||
{
|
||||
id_token_hint: 'id-token',
|
||||
@ -562,36 +571,38 @@ describe('Logout and Revoke Service', () => {
|
||||
post_logout_redirect_uri: 'post-logout-redirect-url',
|
||||
},
|
||||
config,
|
||||
jasmine.anything()
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
|
||||
|
||||
expect(httpHeaders.has('Content-Type')).toBeTrue();
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls dataservice post if logoutOptions with customParams are passed and method is POST', waitForAsync(() => {
|
||||
it('calls dataservice post if logoutOptions with customParams are passed and method is POST', async () => {
|
||||
// Arrange
|
||||
spyOn(urlService, 'getEndSessionUrl').and.returnValue('someValue');
|
||||
vi.spyOn(urlService, 'getEndSessionUrl').mockReturnValue('someValue');
|
||||
|
||||
const redirectSpy = spyOn(redirectService, 'redirectTo');
|
||||
const redirectSpy = vi.spyOn(redirectService, 'redirectTo');
|
||||
|
||||
spyOn(checkSessionService, 'serverStateChanged').and.returnValue(false);
|
||||
spyOn(storagePersistenceService, 'getIdToken').and.returnValue(
|
||||
vi.spyOn(checkSessionService, 'serverStateChanged').mockReturnValue(
|
||||
false
|
||||
);
|
||||
vi.spyOn(storagePersistenceService, 'getIdToken').mockReturnValue(
|
||||
'id-token'
|
||||
);
|
||||
spyOn(urlService, 'getPostLogoutRedirectUrl').and.returnValue(
|
||||
vi.spyOn(urlService, 'getPostLogoutRedirectUrl').mockReturnValue(
|
||||
'post-logout-redirect-url'
|
||||
);
|
||||
spyOn(urlService, 'getEndSessionEndpoint').and.returnValue({
|
||||
vi.spyOn(urlService, 'getEndSessionEndpoint').mockReturnValue({
|
||||
url: 'some-url',
|
||||
existingParams: '',
|
||||
});
|
||||
const postSpy = spyOn(dataService, 'post').and.returnValue(of(null));
|
||||
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of(null));
|
||||
const config = { configId: 'configId1', clientId: 'clientId' };
|
||||
|
||||
// Act
|
||||
@ -607,7 +618,7 @@ describe('Logout and Revoke Service', () => {
|
||||
// Assert
|
||||
result$.subscribe(() => {
|
||||
expect(redirectSpy).not.toHaveBeenCalled();
|
||||
expect(postSpy).toHaveBeenCalledOnceWith(
|
||||
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'some-url',
|
||||
{
|
||||
id_token_hint: 'id-token',
|
||||
@ -618,23 +629,23 @@ describe('Logout and Revoke Service', () => {
|
||||
ui_locales: 'de fr en',
|
||||
},
|
||||
config,
|
||||
jasmine.anything()
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
|
||||
|
||||
expect(httpHeaders.has('Content-Type')).toBeTrue();
|
||||
expect(httpHeaders.has('Content-Type')).toBeTruthy();
|
||||
expect(httpHeaders.get('Content-Type')).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
);
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('logoffLocal', () => {
|
||||
it('calls flowsService.resetAuthorizationData', () => {
|
||||
// Arrange
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
@ -649,25 +660,25 @@ describe('Logout and Revoke Service', () => {
|
||||
});
|
||||
|
||||
describe('logoffAndRevokeTokens', () => {
|
||||
it('calls revokeRefreshToken and revokeAccessToken when storage holds a refreshtoken', waitForAsync(() => {
|
||||
it('calls revokeRefreshToken and revokeAccessToken when storage holds a refreshtoken', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ revocationEndpoint: 'revocationEndpoint' });
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ revocationEndpoint: 'revocationEndpoint' })
|
||||
);
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
const revokeRefreshTokenSpy = spyOn(
|
||||
service,
|
||||
'revokeRefreshToken'
|
||||
).and.returnValue(of({ any: 'thing' }));
|
||||
const revokeAccessTokenSpy = spyOn(
|
||||
service,
|
||||
'revokeAccessToken'
|
||||
).and.returnValue(of({ any: 'thing' }));
|
||||
const revokeRefreshTokenSpy = vi
|
||||
.spyOn(service, 'revokeRefreshToken')
|
||||
.mockReturnValue(of({ any: 'thing' }));
|
||||
const revokeAccessTokenSpy = vi
|
||||
.spyOn(service, 'revokeAccessToken')
|
||||
.mockReturnValue(of({ any: 'thing' }));
|
||||
|
||||
// Act
|
||||
service.logoffAndRevokeTokens(config, [config]).subscribe(() => {
|
||||
@ -675,25 +686,27 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(revokeRefreshTokenSpy).toHaveBeenCalled();
|
||||
expect(revokeAccessTokenSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('logs error when revokeaccesstoken throws an error', waitForAsync(() => {
|
||||
it('logs error when revokeaccesstoken throws an error', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ revocationEndpoint: 'revocationEndpoint' });
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ revocationEndpoint: 'revocationEndpoint' })
|
||||
);
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(service, 'revokeRefreshToken').and.returnValue(
|
||||
vi.spyOn(service, 'revokeRefreshToken').mockReturnValue(
|
||||
of({ any: 'thing' })
|
||||
);
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
spyOn(service, 'revokeAccessToken').and.returnValue(
|
||||
vi.spyOn(service, 'revokeAccessToken').mockReturnValue(
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
@ -704,20 +717,22 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls logoff in case of success', waitForAsync(() => {
|
||||
it('calls logoff in case of success', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(service, 'revokeRefreshToken').and.returnValue(
|
||||
vi.spyOn(service, 'revokeRefreshToken').mockReturnValue(
|
||||
of({ any: 'thing' })
|
||||
);
|
||||
spyOn(service, 'revokeAccessToken').and.returnValue(of({ any: 'thing' }));
|
||||
const logoffSpy = spyOn(service, 'logoff').and.returnValue(of(null));
|
||||
vi.spyOn(service, 'revokeAccessToken').mockReturnValue(
|
||||
of({ any: 'thing' })
|
||||
);
|
||||
const logoffSpy = vi.spyOn(service, 'logoff').mockReturnValue(of(null));
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
// Act
|
||||
@ -725,20 +740,22 @@ describe('Logout and Revoke Service', () => {
|
||||
// Assert
|
||||
expect(logoffSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls logoff with urlhandler in case of success', waitForAsync(() => {
|
||||
it('calls logoff with urlhandler in case of success', async () => {
|
||||
// Arrange
|
||||
const paramToken = 'damien';
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue(
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
paramToken
|
||||
);
|
||||
spyOn(service, 'revokeRefreshToken').and.returnValue(
|
||||
vi.spyOn(service, 'revokeRefreshToken').mockReturnValue(
|
||||
of({ any: 'thing' })
|
||||
);
|
||||
spyOn(service, 'revokeAccessToken').and.returnValue(of({ any: 'thing' }));
|
||||
const logoffSpy = spyOn(service, 'logoff').and.returnValue(of(null));
|
||||
vi.spyOn(service, 'revokeAccessToken').mockReturnValue(
|
||||
of({ any: 'thing' })
|
||||
);
|
||||
const logoffSpy = vi.spyOn(service, 'logoff').mockReturnValue(of(null));
|
||||
const urlHandler = (_url: string): void => undefined;
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
@ -747,26 +764,29 @@ describe('Logout and Revoke Service', () => {
|
||||
.logoffAndRevokeTokens(config, [config], { urlHandler })
|
||||
.subscribe(() => {
|
||||
// Assert
|
||||
expect(logoffSpy).toHaveBeenCalledOnceWith(config, [config], {
|
||||
expect(logoffSpy).toHaveBeenCalledExactlyOnceWith(config, [config], {
|
||||
urlHandler,
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('calls revokeAccessToken when storage does not hold a refreshtoken', waitForAsync(() => {
|
||||
it('calls revokeAccessToken when storage does not hold a refreshtoken', async () => {
|
||||
// Arrange
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ revocationEndpoint: 'revocationEndpoint' });
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ revocationEndpoint: 'revocationEndpoint' })
|
||||
);
|
||||
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue('');
|
||||
const revokeRefreshTokenSpy = spyOn(service, 'revokeRefreshToken');
|
||||
const revokeAccessTokenSpy = spyOn(
|
||||
service,
|
||||
'revokeAccessToken'
|
||||
).and.returnValue(of({ any: 'thing' }));
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
''
|
||||
);
|
||||
const revokeRefreshTokenSpy = vi.spyOn(service, 'revokeRefreshToken');
|
||||
const revokeAccessTokenSpy = vi
|
||||
.spyOn(service, 'revokeAccessToken')
|
||||
.mockReturnValue(of({ any: 'thing' }));
|
||||
|
||||
// Act
|
||||
service.logoffAndRevokeTokens(config, [config]).subscribe(() => {
|
||||
@ -774,19 +794,23 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(revokeRefreshTokenSpy).not.toHaveBeenCalled();
|
||||
expect(revokeAccessTokenSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('logs error when revokeaccesstoken throws an error', waitForAsync(() => {
|
||||
it('logs error when revokeaccesstoken throws an error', async () => {
|
||||
// Arrange
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(storagePersistenceService, 'read')
|
||||
.withArgs('authWellKnownEndPoints', config)
|
||||
.and.returnValue({ revocationEndpoint: 'revocationEndpoint' });
|
||||
spyOn(storagePersistenceService, 'getRefreshToken').and.returnValue('');
|
||||
const loggerSpy = spyOn(loggerService, 'logError');
|
||||
mockImplementationWhenArgsEqual(
|
||||
vi.spyOn(storagePersistenceService, 'read'),
|
||||
['authWellKnownEndPoints', config],
|
||||
() => ({ revocationEndpoint: 'revocationEndpoint' })
|
||||
);
|
||||
vi.spyOn(storagePersistenceService, 'getRefreshToken').mockReturnValue(
|
||||
''
|
||||
);
|
||||
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
||||
|
||||
spyOn(service, 'revokeAccessToken').and.returnValue(
|
||||
vi.spyOn(service, 'revokeAccessToken').mockReturnValue(
|
||||
throwError(() => new Error('Error'))
|
||||
);
|
||||
|
||||
@ -797,18 +821,18 @@ describe('Logout and Revoke Service', () => {
|
||||
expect(err).toBeTruthy();
|
||||
},
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('logoffLocalMultiple', () => {
|
||||
it('calls logoffLocal for every config which is present', () => {
|
||||
// Arrange
|
||||
const allConfigs = [{ configId: 'configId1' }, { configId: 'configId2' }];
|
||||
const resetAuthorizationDataSpy = spyOn(
|
||||
const resetAuthorizationDataSpy = vi.spyOn(
|
||||
resetAuthDataService,
|
||||
'resetAuthorizationData'
|
||||
);
|
||||
const checkSessionServiceSpy = spyOn(checkSessionService, 'stop');
|
||||
const checkSessionServiceSpy = vi.spyOn(checkSessionService, 'stop');
|
||||
|
||||
// Act
|
||||
service.logoffLocalMultiple(allConfigs);
|
||||
@ -816,8 +840,8 @@ describe('Logout and Revoke Service', () => {
|
||||
// Assert
|
||||
expect(resetAuthorizationDataSpy).toHaveBeenCalledTimes(2);
|
||||
expect(checkSessionServiceSpy).toHaveBeenCalledTimes(2);
|
||||
expect(resetAuthorizationDataSpy.calls.allArgs()).toEqual([
|
||||
[allConfigs[0], allConfigs],
|
||||
expect(resetAuthorizationDataSpy).toBeCalledWith([
|
||||
[allConfigs[0]!, allConfigs],
|
||||
[allConfigs[1], allConfigs],
|
||||
]);
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, concatMap, retry, switchMap } from 'rxjs/operators';
|
||||
import { DataService } from '../api/data.service';
|
||||
import { LogoutAuthOptions } from '../auth-options';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { LogoutAuthOptions } from '../auth-options';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { ResetAuthDataService } from '../flows/reset-auth-data.service';
|
||||
import { CheckSessionService } from '../iframe/check-session.service';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,28 +1,28 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { concatMap, map } from 'rxjs/operators';
|
||||
import { AuthOptions, LogoutAuthOptions } from './auth-options';
|
||||
import { AuthenticatedResult } from './auth-state/auth-result';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { toSignal } from 'injection-js/rxjs-interop';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { concatMap, map, shareReplay } from 'rxjs/operators';
|
||||
import type { AuthOptions, LogoutAuthOptions } from './auth-options';
|
||||
import type { AuthenticatedResult } from './auth-state/auth-result';
|
||||
import { AuthStateService } from './auth-state/auth-state.service';
|
||||
import { CheckAuthService } from './auth-state/check-auth.service';
|
||||
import { CallbackService } from './callback/callback.service';
|
||||
import { RefreshSessionService } from './callback/refresh-session.service';
|
||||
import { AuthWellKnownEndpoints } from './config/auth-well-known/auth-well-known-endpoints';
|
||||
import type { AuthWellKnownEndpoints } from './config/auth-well-known/auth-well-known-endpoints';
|
||||
import { AuthWellKnownService } from './config/auth-well-known/auth-well-known.service';
|
||||
import { ConfigurationService } from './config/config.service';
|
||||
import { OpenIdConfiguration } from './config/openid-configuration';
|
||||
import { AuthResult } from './flows/callback-context';
|
||||
import type { OpenIdConfiguration } from './config/openid-configuration';
|
||||
import type { AuthResult } from './flows/callback-context';
|
||||
import { FlowsDataService } from './flows/flows-data.service';
|
||||
import { CheckSessionService } from './iframe/check-session.service';
|
||||
import { LoginResponse } from './login/login-response';
|
||||
import type { LoginResponse } from './login/login-response';
|
||||
import { LoginService } from './login/login.service';
|
||||
import { PopupOptions } from './login/popup/popup-options';
|
||||
import type { PopupOptions } from './login/popup/popup-options';
|
||||
import { LogoffRevocationService } from './logoff-revoke/logoff-revocation.service';
|
||||
import { UserService } from './user-data/user.service';
|
||||
import { UserDataResult } from './user-data/userdata-result';
|
||||
import type { UserDataResult } from './user-data/userdata-result';
|
||||
import { TokenHelperService } from './utils/tokenHelper/token-helper.service';
|
||||
import { UrlService } from './utils/url/url.service';
|
||||
import { toSignal } from 'injection-js/rxjs-interop';
|
||||
|
||||
@Injectable()
|
||||
export class OidcSecurityService {
|
||||
@ -355,10 +355,17 @@ export class OidcSecurityService {
|
||||
* @param configId The configId to perform the action in behalf of. If not passed, the first configs will be taken
|
||||
* @param authOptions The custom options for the the authentication request.
|
||||
*/
|
||||
authorize(configId?: string, authOptions?: AuthOptions): void {
|
||||
this.configurationService
|
||||
authorize(configId?: string, authOptions?: AuthOptions): Observable<void> {
|
||||
const result$ = this.configurationService
|
||||
.getOpenIDConfiguration(configId)
|
||||
.subscribe((config) => this.loginService.login(config, authOptions));
|
||||
.pipe(
|
||||
map((config) => this.loginService.login(config, authOptions)),
|
||||
shareReplay(1)
|
||||
);
|
||||
|
||||
result$.subscribe();
|
||||
|
||||
return result$;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -471,24 +478,34 @@ export class OidcSecurityService {
|
||||
*
|
||||
* @param configId The configId to perform the action in behalf of. If not passed, the first configs will be taken
|
||||
*/
|
||||
logoffLocal(configId?: string): void {
|
||||
this.configurationService
|
||||
logoffLocal(configId?: string): Observable<void> {
|
||||
const result$ = this.configurationService
|
||||
.getOpenIDConfigurations(configId)
|
||||
.subscribe(({ allConfigs, currentConfig }) =>
|
||||
this.logoffRevocationService.logoffLocal(currentConfig, allConfigs)
|
||||
.pipe(
|
||||
map(({ allConfigs, currentConfig }) =>
|
||||
this.logoffRevocationService.logoffLocal(currentConfig, allConfigs)
|
||||
),
|
||||
shareReplay(1)
|
||||
);
|
||||
result$.subscribe();
|
||||
return result$;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the user out of the application for all configs without logging them out of the server.
|
||||
* Use this method if you have _multiple_ configs enabled.
|
||||
*/
|
||||
logoffLocalMultiple(): void {
|
||||
this.configurationService
|
||||
.getOpenIDConfigurations()
|
||||
.subscribe(({ allConfigs }) =>
|
||||
logoffLocalMultiple(): Observable<void> {
|
||||
const result$ = this.configurationService.getOpenIDConfigurations().pipe(
|
||||
map(({ allConfigs }) =>
|
||||
this.logoffRevocationService.logoffLocalMultiple(allConfigs)
|
||||
);
|
||||
),
|
||||
shareReplay(1)
|
||||
);
|
||||
|
||||
result$.subscribe();
|
||||
|
||||
return result$;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { APP_INITIALIZER } from '@angular/core';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed, createSpyObj } from '@/testing';
|
||||
import { mockProvider } from '@/testing/mock';
|
||||
import { APP_INITIALIZER } from 'oidc-client-rx';
|
||||
import { of } from 'rxjs';
|
||||
import { mockProvider } from '../test/auto-mock';
|
||||
import { PASSED_CONFIG } from './auth-config';
|
||||
import { ConfigurationService } from './config/config.service';
|
||||
import {
|
||||
@ -14,14 +14,14 @@ import { provideAuth, withAppInitializerAuthCheck } from './provide-auth';
|
||||
|
||||
describe('provideAuth', () => {
|
||||
describe('APP_CONFIG', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
providers: [
|
||||
provideAuth({ config: { authority: 'something' } }),
|
||||
mockProvider(ConfigurationService),
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should provide config', () => {
|
||||
const config = TestBed.inject(PASSED_CONFIG);
|
||||
@ -37,8 +37,8 @@ describe('provideAuth', () => {
|
||||
});
|
||||
|
||||
describe('StsConfigHttpLoader', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
providers: [
|
||||
provideAuth({
|
||||
loader: {
|
||||
@ -49,7 +49,7 @@ describe('provideAuth', () => {
|
||||
mockProvider(ConfigurationService),
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should create StsConfigStaticLoader if config is passed', () => {
|
||||
const configLoader = TestBed.inject(StsConfigLoader);
|
||||
@ -59,14 +59,14 @@ describe('provideAuth', () => {
|
||||
});
|
||||
|
||||
describe('features', () => {
|
||||
let oidcSecurityServiceMock: jasmine.SpyObj<OidcSecurityService>;
|
||||
let oidcSecurityServiceMock: OidcSecurityService;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
oidcSecurityServiceMock = jasmine.createSpyObj<OidcSecurityService>(
|
||||
beforeEach(async () => {
|
||||
oidcSecurityServiceMock = createSpyObj<OidcSecurityService>(
|
||||
'OidcSecurityService',
|
||||
['checkAuthMultiple']
|
||||
);
|
||||
TestBed.configureTestingModule({
|
||||
await TestBed.configureTestingModule({
|
||||
providers: [
|
||||
provideAuth(
|
||||
{ config: { authority: 'something' } },
|
||||
@ -79,14 +79,15 @@ describe('provideAuth', () => {
|
||||
},
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
});
|
||||
|
||||
it('should provide APP_INITIALIZER config', () => {
|
||||
const config = TestBed.inject(APP_INITIALIZER);
|
||||
|
||||
expect(config.length)
|
||||
.withContext('Expected an APP_INITIALIZER to be registered')
|
||||
.toBe(1);
|
||||
expect(
|
||||
config.length,
|
||||
'Expected an APP_INITIALIZER to be registered'
|
||||
).toBe(1);
|
||||
expect(oidcSecurityServiceMock.checkAuthMultiple).toHaveBeenCalledTimes(
|
||||
1
|
||||
);
|
||||
|
@ -1,15 +1,11 @@
|
||||
import type { Provider } from 'injection-js';
|
||||
import {
|
||||
APP_INITIALIZER,
|
||||
EnvironmentProviders,
|
||||
makeEnvironmentProviders,
|
||||
Provider,
|
||||
} from 'injection-js';
|
||||
import {
|
||||
createStaticLoader,
|
||||
PASSED_CONFIG,
|
||||
PassedInitialConfig,
|
||||
type PassedInitialConfig,
|
||||
createStaticLoader,
|
||||
} from './auth-config';
|
||||
import { StsConfigLoader } from './config/loader/config-loader';
|
||||
import { APP_INITIALIZER } from './injection';
|
||||
import { AbstractLoggerService } from './logging/abstract-logger.service';
|
||||
import { ConsoleLoggerService } from './logging/console-logger.service';
|
||||
import { OidcSecurityService } from './oidc.security.service';
|
||||
@ -26,14 +22,14 @@ export interface AuthFeature {
|
||||
export function provideAuth(
|
||||
passedConfig: PassedInitialConfig,
|
||||
...features: AuthFeature[]
|
||||
): EnvironmentProviders {
|
||||
): Provider[] {
|
||||
const providers = _provideAuth(passedConfig);
|
||||
|
||||
for (const feature of features) {
|
||||
providers.push(...feature.ɵproviders);
|
||||
}
|
||||
|
||||
return makeEnvironmentProviders(providers);
|
||||
return providers;
|
||||
}
|
||||
|
||||
export function _provideAuth(passedConfig: PassedInitialConfig): Provider[] {
|
||||
|
@ -1,17 +1,18 @@
|
||||
// biome-ignore lint/nursery/noEnum: <explanation>
|
||||
export enum EventTypes {
|
||||
/**
|
||||
* This only works in the AppModule Constructor
|
||||
*/
|
||||
ConfigLoaded,
|
||||
CheckingAuth,
|
||||
CheckingAuthFinished,
|
||||
CheckingAuthFinishedWithError,
|
||||
ConfigLoadingFailed,
|
||||
CheckSessionReceived,
|
||||
UserDataChanged,
|
||||
NewAuthenticationResult,
|
||||
TokenExpired,
|
||||
IdTokenExpired,
|
||||
SilentRenewStarted,
|
||||
SilentRenewFailed,
|
||||
ConfigLoaded = 0,
|
||||
CheckingAuth = 1,
|
||||
CheckingAuthFinished = 2,
|
||||
CheckingAuthFinishedWithError = 3,
|
||||
ConfigLoadingFailed = 4,
|
||||
CheckSessionReceived = 5,
|
||||
UserDataChanged = 6,
|
||||
NewAuthenticationResult = 7,
|
||||
TokenExpired = 8,
|
||||
IdTokenExpired = 9,
|
||||
SilentRenewStarted = 10,
|
||||
SilentRenewFailed = 11,
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { vi } from 'vitest';
|
||||
import { EventTypes } from './event-types';
|
||||
import { PublicEventsService } from './public-events.service';
|
||||
|
||||
@ -20,7 +21,7 @@ describe('Events Service', () => {
|
||||
expect(eventsService).toBeTruthy();
|
||||
});
|
||||
|
||||
it('registering to single event with one event emit works', waitForAsync(() => {
|
||||
it('registering to single event with one event emit works', async () => {
|
||||
eventsService.registerForEvents().subscribe((firedEvent) => {
|
||||
expect(firedEvent).toBeTruthy();
|
||||
expect(firedEvent).toEqual({
|
||||
@ -29,9 +30,9 @@ describe('Events Service', () => {
|
||||
});
|
||||
});
|
||||
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
|
||||
}));
|
||||
});
|
||||
|
||||
it('registering to single event with multiple same event emit works', waitForAsync(() => {
|
||||
it('registering to single event with multiple same event emit works', async () => {
|
||||
const spy = jasmine.createSpy('spy');
|
||||
|
||||
eventsService.registerForEvents().subscribe((firedEvent) => {
|
||||
@ -50,9 +51,9 @@ describe('Events Service', () => {
|
||||
type: EventTypes.ConfigLoaded,
|
||||
value: { myKey: 'myValue2' },
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
it('registering to single event with multiple emit works', waitForAsync(() => {
|
||||
it('registering to single event with multiple emit works', async () => {
|
||||
eventsService
|
||||
.registerForEvents()
|
||||
.pipe(filter((x) => x.type === EventTypes.ConfigLoaded))
|
||||
@ -65,5 +66,5 @@ describe('Events Service', () => {
|
||||
});
|
||||
eventsService.fireEvent(EventTypes.ConfigLoaded, { myKey: 'myValue' });
|
||||
eventsService.fireEvent(EventTypes.NewAuthenticationResult, true);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
27
src/router/index.ts
Normal file
27
src/router/index.ts
Normal file
@ -0,0 +1,27 @@
|
||||
export type RouteData = {
|
||||
[key: string | symbol]: any;
|
||||
};
|
||||
|
||||
export interface ActivatedRouteSnapshot {
|
||||
data: RouteData;
|
||||
}
|
||||
|
||||
export interface RouterStateSnapshot {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export abstract class AbstractRouter {
|
||||
navigateByUrl(url: string): void {
|
||||
// TODO
|
||||
// Implementation of navigating to a URL
|
||||
}
|
||||
|
||||
getCurrentNavigation(): any {
|
||||
// TODO
|
||||
// Implementation of getting the current navigation
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO
|
||||
parseUrl(url: string) {}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { mockClass, mockProvider } from '../../test/auto-mock';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { mockClass, mockProvider } from '../testing/mock';
|
||||
import { AbstractSecurityStorage } from './abstract-security-storage';
|
||||
import { BrowserStorageService } from './browser-storage.service';
|
||||
import { DefaultSessionStorageService } from './default-sessionstorage.service';
|
||||
@ -34,7 +35,7 @@ describe('BrowserStorageService', () => {
|
||||
it('returns null if there is no storage', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(false);
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(false);
|
||||
|
||||
expect(service.read('anything', config)).toBeNull();
|
||||
});
|
||||
@ -42,7 +43,7 @@ describe('BrowserStorageService', () => {
|
||||
it('returns null if getItem returns null', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(true);
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
|
||||
const result = service.read('anything', config);
|
||||
|
||||
@ -52,10 +53,10 @@ describe('BrowserStorageService', () => {
|
||||
it('returns the item if getItem returns an item', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(true);
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
const returnValue = `{ "name":"John", "age":30, "city":"New York"}`;
|
||||
|
||||
spyOn(abstractSecurityStorage, 'read').and.returnValue(returnValue);
|
||||
vi.spyOn(abstractSecurityStorage, 'read').mockReturnValue(returnValue);
|
||||
const result = service.read('anything', config);
|
||||
|
||||
expect(result).toEqual(JSON.parse(returnValue));
|
||||
@ -66,24 +67,21 @@ describe('BrowserStorageService', () => {
|
||||
it('returns false if there is no storage', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(false);
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(false);
|
||||
|
||||
expect(service.write('anyvalue', config)).toBeFalse();
|
||||
expect(service.write('anyvalue', config)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('writes object correctly with configId', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(true);
|
||||
const writeSpy = spyOn(
|
||||
abstractSecurityStorage,
|
||||
'write'
|
||||
).and.callThrough();
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
const writeSpy = vi.spyOn(abstractSecurityStorage, 'write')();
|
||||
|
||||
const result = service.write({ anyKey: 'anyvalue' }, config);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(writeSpy).toHaveBeenCalledOnceWith(
|
||||
expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'configId1',
|
||||
JSON.stringify({ anyKey: 'anyvalue' })
|
||||
);
|
||||
@ -92,18 +90,15 @@ describe('BrowserStorageService', () => {
|
||||
it('writes null if item is falsy', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(true);
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
|
||||
const writeSpy = spyOn(
|
||||
abstractSecurityStorage,
|
||||
'write'
|
||||
).and.callThrough();
|
||||
const writeSpy = vi.spyOn(abstractSecurityStorage, 'write')();
|
||||
const somethingFalsy = '';
|
||||
|
||||
const result = service.write(somethingFalsy, config);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(writeSpy).toHaveBeenCalledOnceWith(
|
||||
expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
'configId1',
|
||||
JSON.stringify(null)
|
||||
);
|
||||
@ -114,41 +109,35 @@ describe('BrowserStorageService', () => {
|
||||
it('returns false if there is no storage', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(false);
|
||||
expect(service.remove('anything', config)).toBeFalse();
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(false);
|
||||
expect(service.remove('anything', config)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns true if removeItem is called', () => {
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(true);
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
const setItemSpy = spyOn(
|
||||
abstractSecurityStorage,
|
||||
'remove'
|
||||
).and.callThrough();
|
||||
const setItemSpy = vi.spyOn(abstractSecurityStorage, 'remove')();
|
||||
|
||||
const result = service.remove('anyKey', config);
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(setItemSpy).toHaveBeenCalledOnceWith('anyKey');
|
||||
expect(setItemSpy).toHaveBeenCalledExactlyOnceWith('anyKey');
|
||||
});
|
||||
});
|
||||
|
||||
describe('clear', () => {
|
||||
it('returns false if there is no storage', () => {
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(false);
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(false);
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
expect(service.clear(config)).toBeFalse();
|
||||
expect(service.clear(config)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns true if clear is called', () => {
|
||||
spyOn(service as any, 'hasStorage').and.returnValue(true);
|
||||
vi.spyOn(service as any, 'hasStorage').mockReturnValue(true);
|
||||
|
||||
const setItemSpy = spyOn(
|
||||
abstractSecurityStorage,
|
||||
'clear'
|
||||
).and.callThrough();
|
||||
const setItemSpy = vi.spyOn(abstractSecurityStorage, 'clear')();
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
const result = service.clear(config);
|
||||
@ -161,7 +150,7 @@ describe('BrowserStorageService', () => {
|
||||
describe('hasStorage', () => {
|
||||
it('returns false if there is no storage', () => {
|
||||
(Storage as any) = undefined;
|
||||
expect((service as any).hasStorage()).toBeFalse();
|
||||
expect((service as any).hasStorage()).toBeFalsy();
|
||||
Storage = Storage;
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { DefaultLocalStorageService } from './default-localstorage.service';
|
||||
|
||||
describe('DefaultLocalStorageService', () => {
|
||||
@ -20,37 +21,37 @@ describe('DefaultLocalStorageService', () => {
|
||||
|
||||
describe('read', () => {
|
||||
it('should call localstorage.getItem', () => {
|
||||
const spy = spyOn(localStorage, 'getItem');
|
||||
const spy = vi.spyOn(localStorage, 'getItem');
|
||||
|
||||
service.read('henlo');
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('henlo');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('henlo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('write', () => {
|
||||
it('should call localstorage.setItem', () => {
|
||||
const spy = spyOn(localStorage, 'setItem');
|
||||
const spy = vi.spyOn(localStorage, 'setItem');
|
||||
|
||||
service.write('henlo', 'furiend');
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('henlo', 'furiend');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('henlo', 'furiend');
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove', () => {
|
||||
it('should call localstorage.removeItem', () => {
|
||||
const spy = spyOn(localStorage, 'removeItem');
|
||||
const spy = vi.spyOn(localStorage, 'removeItem');
|
||||
|
||||
service.remove('henlo');
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('henlo');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('henlo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('clear', () => {
|
||||
it('should call localstorage.clear', () => {
|
||||
const spy = spyOn(localStorage, 'clear');
|
||||
const spy = vi.spyOn(localStorage, 'clear');
|
||||
|
||||
service.clear();
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { DefaultSessionStorageService } from './default-sessionstorage.service';
|
||||
|
||||
describe('DefaultSessionStorageService', () => {
|
||||
@ -20,37 +21,37 @@ describe('DefaultSessionStorageService', () => {
|
||||
|
||||
describe('read', () => {
|
||||
it('should call sessionstorage.getItem', () => {
|
||||
const spy = spyOn(sessionStorage, 'getItem');
|
||||
const spy = vi.spyOn(sessionStorage, 'getItem');
|
||||
|
||||
service.read('henlo');
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('henlo');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('henlo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('write', () => {
|
||||
it('should call sessionstorage.setItem', () => {
|
||||
const spy = spyOn(sessionStorage, 'setItem');
|
||||
const spy = vi.spyOn(sessionStorage, 'setItem');
|
||||
|
||||
service.write('henlo', 'furiend');
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('henlo', 'furiend');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('henlo', 'furiend');
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove', () => {
|
||||
it('should call sessionstorage.removeItem', () => {
|
||||
const spy = spyOn(sessionStorage, 'removeItem');
|
||||
const spy = vi.spyOn(sessionStorage, 'removeItem');
|
||||
|
||||
service.remove('henlo');
|
||||
|
||||
expect(spy).toHaveBeenCalledOnceWith('henlo');
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('henlo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('clear', () => {
|
||||
it('should call sessionstorage.clear', () => {
|
||||
const spy = spyOn(sessionStorage, 'clear');
|
||||
const spy = vi.spyOn(sessionStorage, 'clear');
|
||||
|
||||
service.clear();
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { mockProvider } from '../../test/auto-mock';
|
||||
import { TestBed } from '@/testing';
|
||||
import { vi } from 'vitest';
|
||||
import { mockProvider } from '../testing/mock';
|
||||
import { BrowserStorageService } from './browser-storage.service';
|
||||
import { StoragePersistenceService } from './storage-persistence.service';
|
||||
|
||||
@ -25,16 +26,16 @@ describe('Storage Persistence Service', () => {
|
||||
describe('read', () => {
|
||||
it('reads from oidcSecurityStorage with configId', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const spy = spyOn(securityStorage, 'read');
|
||||
const spy = vi.spyOn(securityStorage, 'read');
|
||||
|
||||
service.read('authNonce', config);
|
||||
expect(spy).toHaveBeenCalledOnceWith('authNonce', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authNonce', config);
|
||||
});
|
||||
|
||||
it('returns undefined (not throws exception) if key to read is not present on config', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
|
||||
spyOn(securityStorage, 'read').and.returnValue({ some: 'thing' });
|
||||
vi.spyOn(securityStorage, 'read').mockReturnValue({ some: 'thing' });
|
||||
const result = service.read('authNonce', config);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
@ -44,13 +45,13 @@ describe('Storage Persistence Service', () => {
|
||||
describe('write', () => {
|
||||
it('writes to oidcSecurityStorage with correct key and correct config', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const readSpy = spyOn(securityStorage, 'read');
|
||||
const writeSpy = spyOn(securityStorage, 'write');
|
||||
const readSpy = vi.spyOn(securityStorage, 'read');
|
||||
const writeSpy = vi.spyOn(securityStorage, 'write');
|
||||
|
||||
service.write('authNonce', 'anyValue', config);
|
||||
|
||||
expect(readSpy).toHaveBeenCalledOnceWith('authNonce', config);
|
||||
expect(writeSpy).toHaveBeenCalledOnceWith(
|
||||
expect(readSpy).toHaveBeenCalledExactlyOnceWith('authNonce', config);
|
||||
expect(writeSpy).toHaveBeenCalledExactlyOnceWith(
|
||||
{ authNonce: 'anyValue' },
|
||||
config
|
||||
);
|
||||
@ -60,32 +61,32 @@ describe('Storage Persistence Service', () => {
|
||||
describe('remove', () => {
|
||||
it('should remove key from config', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const readSpy = spyOn(securityStorage, 'read').and.returnValue({
|
||||
const readSpy = vi.spyOn(securityStorage, 'read').mockReturnValue({
|
||||
authNonce: 'anyValue',
|
||||
});
|
||||
const writeSpy = spyOn(securityStorage, 'write');
|
||||
const writeSpy = vi.spyOn(securityStorage, 'write');
|
||||
|
||||
service.remove('authNonce', config);
|
||||
|
||||
expect(readSpy).toHaveBeenCalledOnceWith('authNonce', config);
|
||||
expect(writeSpy).toHaveBeenCalledOnceWith({}, config);
|
||||
expect(readSpy).toHaveBeenCalledExactlyOnceWith('authNonce', config);
|
||||
expect(writeSpy).toHaveBeenCalledExactlyOnceWith({}, config);
|
||||
});
|
||||
|
||||
it('does not crash when read with configId returns null', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const readSpy = spyOn(securityStorage, 'read').and.returnValue(null);
|
||||
const writeSpy = spyOn(securityStorage, 'write');
|
||||
const readSpy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
|
||||
const writeSpy = vi.spyOn(securityStorage, 'write');
|
||||
|
||||
service.remove('authNonce', config);
|
||||
|
||||
expect(readSpy).toHaveBeenCalledOnceWith('authNonce', config);
|
||||
expect(writeSpy).toHaveBeenCalledOnceWith({}, config);
|
||||
expect(readSpy).toHaveBeenCalledExactlyOnceWith('authNonce', config);
|
||||
expect(writeSpy).toHaveBeenCalledExactlyOnceWith({}, config);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clear', () => {
|
||||
it('should call oidcSecurityStorage.clear()', () => {
|
||||
const clearSpy = spyOn(securityStorage, 'clear');
|
||||
const clearSpy = vi.spyOn(securityStorage, 'clear');
|
||||
|
||||
service.clear({});
|
||||
|
||||
@ -96,49 +97,58 @@ describe('Storage Persistence Service', () => {
|
||||
describe('resetStorageFlowData', () => {
|
||||
it('resets the correct values', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const spy = spyOn(service, 'remove');
|
||||
const spy = vi.spyOn(service, 'remove');
|
||||
|
||||
service.resetStorageFlowData(config);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(10);
|
||||
expect(spy.calls.argsFor(0)).toEqual(['session_state', config]);
|
||||
expect(spy.calls.argsFor(1)).toEqual([
|
||||
expect(vi.mocked(spy).mock.calls[0]).toEqual(['session_state', config]);
|
||||
expect(vi.mocked(spy).mock.calls[1]).toEqual([
|
||||
'storageSilentRenewRunning',
|
||||
config,
|
||||
]);
|
||||
expect(spy.calls.argsFor(2)).toEqual([
|
||||
expect(vi.mocked(spy).mock.calls[2]).toEqual([
|
||||
'storageCodeFlowInProgress',
|
||||
config,
|
||||
]);
|
||||
expect(spy.calls.argsFor(3)).toEqual(['codeVerifier', config]);
|
||||
expect(spy.calls.argsFor(4)).toEqual(['userData', config]);
|
||||
expect(spy.calls.argsFor(5)).toEqual([
|
||||
expect(vi.mocked(spy).mock.calls[3]).toEqual(['codeVerifier', config]);
|
||||
expect(vi.mocked(spy).mock.calls[4]).toEqual(['userData', config]);
|
||||
expect(vi.mocked(spy).mock.calls[5]).toEqual([
|
||||
'storageCustomParamsAuthRequest',
|
||||
config,
|
||||
]);
|
||||
expect(spy.calls.argsFor(6)).toEqual(['access_token_expires_at', config]);
|
||||
expect(spy.calls.argsFor(7)).toEqual([
|
||||
expect(vi.mocked(spy).mock.calls[6]).toEqual([
|
||||
'access_token_expires_at',
|
||||
config,
|
||||
]);
|
||||
expect(vi.mocked(spy).mock.calls[7]).toEqual([
|
||||
'storageCustomParamsRefresh',
|
||||
config,
|
||||
]);
|
||||
expect(spy.calls.argsFor(8)).toEqual([
|
||||
expect(vi.mocked(spy).mock.calls[8]).toEqual([
|
||||
'storageCustomParamsEndSession',
|
||||
config,
|
||||
]);
|
||||
expect(spy.calls.argsFor(9)).toEqual(['reusable_refresh_token', config]);
|
||||
expect(vi.mocked(spy).mock.calls[9]).toEqual([
|
||||
'reusable_refresh_token',
|
||||
config,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetAuthStateInStorage', () => {
|
||||
it('resets the correct values', () => {
|
||||
const config = { configId: 'configId1' };
|
||||
const spy = spyOn(service, 'remove');
|
||||
const spy = vi.spyOn(service, 'remove');
|
||||
|
||||
service.resetAuthStateInStorage(config);
|
||||
|
||||
expect(spy.calls.argsFor(0)).toEqual(['authzData', config]);
|
||||
expect(spy.calls.argsFor(1)).toEqual(['reusable_refresh_token', config]);
|
||||
expect(spy.calls.argsFor(2)).toEqual(['authnResult', config]);
|
||||
expect(vi.mocked(spy).mock.calls[0]).toEqual(['authzData', config]);
|
||||
expect(vi.mocked(spy).mock.calls[1]).toEqual([
|
||||
'reusable_refresh_token',
|
||||
config,
|
||||
]);
|
||||
expect(vi.mocked(spy).mock.calls[2]).toEqual(['authnResult', config]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -146,41 +156,45 @@ describe('Storage Persistence Service', () => {
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns the value', () => {
|
||||
const returnValue = { authzData: 'someValue' };
|
||||
const config = { configId: 'configId1' };
|
||||
const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
|
||||
const spy = vi
|
||||
.spyOn(securityStorage, 'read')
|
||||
.mockReturnValue(returnValue);
|
||||
const result = service.getAccessToken(config);
|
||||
|
||||
expect(result).toBe('someValue');
|
||||
expect(spy).toHaveBeenCalledOnceWith('authzData', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authzData', config);
|
||||
});
|
||||
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
|
||||
const spy = spyOn(securityStorage, 'read').and.returnValue(null);
|
||||
const spy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
|
||||
const config = { configId: 'configId1' };
|
||||
const result = service.getAccessToken(config);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
expect(spy).toHaveBeenCalledOnceWith('authzData', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authzData', config);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getIdToken', () => {
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns the value', () => {
|
||||
const returnValue = { authnResult: { id_token: 'someValue' } };
|
||||
const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
|
||||
const spy = vi
|
||||
.spyOn(securityStorage, 'read')
|
||||
.mockReturnValue(returnValue);
|
||||
const config = { configId: 'configId1' };
|
||||
const result = service.getIdToken(config);
|
||||
|
||||
expect(result).toBe('someValue');
|
||||
expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
|
||||
});
|
||||
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
|
||||
const spy = spyOn(securityStorage, 'read').and.returnValue(null);
|
||||
const spy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
|
||||
const config = { configId: 'configId1' };
|
||||
const result = service.getIdToken(config);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
|
||||
});
|
||||
});
|
||||
|
||||
@ -188,32 +202,36 @@ describe('Storage Persistence Service', () => {
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns the value', () => {
|
||||
const returnValue = { authnResult: { id_token: 'someValue' } };
|
||||
const config = { configId: 'configId1' };
|
||||
const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
|
||||
const spy = vi
|
||||
.spyOn(securityStorage, 'read')
|
||||
.mockReturnValue(returnValue);
|
||||
const result = service.getAuthenticationResult(config);
|
||||
|
||||
expect(result.id_token).toBe('someValue');
|
||||
expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
|
||||
});
|
||||
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
|
||||
const spy = spyOn(securityStorage, 'read').and.returnValue(null);
|
||||
const spy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
|
||||
const config = { configId: 'configId1' };
|
||||
const result = service.getAuthenticationResult(config);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getRefreshToken', () => {
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns the value (refresh token with mandatory rotation - default)', () => {
|
||||
const returnValue = { authnResult: { refresh_token: 'someValue' } };
|
||||
const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
|
||||
const spy = vi
|
||||
.spyOn(securityStorage, 'read')
|
||||
.mockReturnValue(returnValue);
|
||||
const config = { configId: 'configId1' };
|
||||
const result = service.getRefreshToken(config);
|
||||
|
||||
expect(result).toBe('someValue');
|
||||
expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
|
||||
});
|
||||
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns the value (refresh token without rotation)', () => {
|
||||
@ -222,12 +240,12 @@ describe('Storage Persistence Service', () => {
|
||||
configId: 'configId1',
|
||||
allowUnsafeReuseRefreshToken: true,
|
||||
};
|
||||
const spy = spyOn(securityStorage, 'read');
|
||||
const spy = vi.spyOn(securityStorage, 'read');
|
||||
|
||||
spy
|
||||
.withArgs('reusable_refresh_token', config)
|
||||
.and.returnValue(returnValue);
|
||||
spy.withArgs('authnResult', config).and.returnValue(undefined);
|
||||
.mockReturnValue(returnValue);
|
||||
spy.withArgs('authnResult', config).mockReturnValue(undefined);
|
||||
const result = service.getRefreshToken(config);
|
||||
|
||||
expect(result).toBe(returnValue.reusable_refresh_token);
|
||||
@ -238,21 +256,23 @@ describe('Storage Persistence Service', () => {
|
||||
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
|
||||
const returnValue = { authnResult: { NO_refresh_token: 'someValue' } };
|
||||
const spy = spyOn(securityStorage, 'read').and.returnValue(returnValue);
|
||||
const spy = vi
|
||||
.spyOn(securityStorage, 'read')
|
||||
.mockReturnValue(returnValue);
|
||||
const config = { configId: 'configId1' };
|
||||
const result = service.getRefreshToken(config);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
|
||||
});
|
||||
|
||||
it('get calls oidcSecurityStorage.read with correct key and returns null', () => {
|
||||
const spy = spyOn(securityStorage, 'read').and.returnValue(null);
|
||||
const spy = vi.spyOn(securityStorage, 'read').mockReturnValue(null);
|
||||
const config = { configId: 'configId1' };
|
||||
const result = service.getRefreshToken(config);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(spy).toHaveBeenCalledOnceWith('authnResult', config);
|
||||
expect(spy).toHaveBeenCalledExactlyOnceWith('authnResult', config);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { AuthResult } from '../flows/callback-context';
|
||||
import { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { inject } from 'injection-js';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import type { AuthResult } from '../flows/callback-context';
|
||||
import { BrowserStorageService } from './browser-storage.service';
|
||||
|
||||
export type StorageKeys =
|
||||
@ -24,7 +24,6 @@ export type StorageKeys =
|
||||
| 'jwtKeys'
|
||||
| 'popupauth';
|
||||
|
||||
|
||||
export class StoragePersistenceService {
|
||||
private readonly browserStorageService = inject(BrowserStorageService);
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user