feat: init
This commit is contained in:
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user