193 lines
6.3 KiB
TypeScript
193 lines
6.3 KiB
TypeScript
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
|
import { mockImplementationWhenArgs, spyOnWithOrigin } from '@/testing/spy';
|
|
import { vi } from 'vitest';
|
|
import { LogLevel } from '../../logging/log-level';
|
|
import { LoggerService } from '../../logging/logger.service';
|
|
import { mockProvider } from '../../testing/mock';
|
|
import type { OpenIdConfiguration } from '../openid-configuration';
|
|
import { ConfigValidationService } from './config-validation.service';
|
|
import { allMultipleConfigRules } from './rules';
|
|
|
|
describe('Config Validation Service', () => {
|
|
let configValidationService: ConfigValidationService;
|
|
let loggerService: LoggerService;
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({
|
|
providers: [ConfigValidationService, mockProvider(LoggerService)],
|
|
});
|
|
configValidationService = TestBed.inject(ConfigValidationService);
|
|
loggerService = TestBed.inject(LoggerService);
|
|
});
|
|
|
|
const VALID_CONFIG = {
|
|
authority: 'https://offeringsolutions-sts.azurewebsites.net',
|
|
redirectUrl: window.location.origin,
|
|
postLogoutRedirectUri: window.location.origin,
|
|
clientId: 'angularClient',
|
|
scope: 'openid profile email',
|
|
responseType: 'code',
|
|
silentRenew: true,
|
|
silentRenewUrl: `${window.location.origin}/silent-renew.html`,
|
|
renewTimeBeforeTokenExpiresInSeconds: 10,
|
|
logLevel: LogLevel.Debug,
|
|
};
|
|
|
|
it('should create', () => {
|
|
expect(configValidationService).toBeTruthy();
|
|
});
|
|
|
|
it('should return false for empty config', () => {
|
|
const config = {};
|
|
const result = configValidationService.validateConfig(config);
|
|
|
|
expect(result).toBeFalsy();
|
|
});
|
|
|
|
it('should return true for valid config', () => {
|
|
const result = configValidationService.validateConfig(VALID_CONFIG);
|
|
|
|
expect(result).toBeTruthy();
|
|
});
|
|
|
|
it('calls `logWarning` if one rule has warning level', () => {
|
|
const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
|
|
const messageTypeSpy = spyOnWithOrigin(
|
|
configValidationService,
|
|
'getAllMessagesOfType' as any
|
|
);
|
|
|
|
mockImplementationWhenArgs(
|
|
messageTypeSpy,
|
|
(arg1: any, arg2: any) => arg1 === 'warning' && Array.isArray(arg2),
|
|
() => ['A warning message']
|
|
);
|
|
|
|
configValidationService.validateConfig(VALID_CONFIG);
|
|
expect(loggerWarningSpy).toHaveBeenCalled();
|
|
});
|
|
|
|
describe('ensure-clientId.rule', () => {
|
|
it('return false when no clientId is set', () => {
|
|
const config = { ...VALID_CONFIG, clientId: '' } as OpenIdConfiguration;
|
|
const result = configValidationService.validateConfig(config);
|
|
|
|
expect(result).toBeFalsy();
|
|
});
|
|
});
|
|
|
|
describe('ensure-authority-server.rule', () => {
|
|
it('return false when no security token service is set', () => {
|
|
const config = {
|
|
...VALID_CONFIG,
|
|
authority: '',
|
|
} as OpenIdConfiguration;
|
|
const result = configValidationService.validateConfig(config);
|
|
|
|
expect(result).toBeFalsy();
|
|
});
|
|
});
|
|
|
|
describe('ensure-redirect-url.rule', () => {
|
|
it('return false for no redirect Url', () => {
|
|
const config = { ...VALID_CONFIG, redirectUrl: '' };
|
|
const result = configValidationService.validateConfig(config);
|
|
|
|
expect(result).toBeFalsy();
|
|
});
|
|
});
|
|
|
|
describe('ensureSilentRenewUrlWhenNoRefreshTokenUsed', () => {
|
|
it('return false when silent renew is used with no useRefreshToken and no silentrenewUrl', () => {
|
|
const config = {
|
|
...VALID_CONFIG,
|
|
silentRenew: true,
|
|
useRefreshToken: false,
|
|
silentRenewUrl: '',
|
|
} as OpenIdConfiguration;
|
|
const result = configValidationService.validateConfig(config);
|
|
|
|
expect(result).toBeFalsy();
|
|
});
|
|
});
|
|
|
|
describe('use-offline-scope-with-silent-renew.rule', () => {
|
|
it('return true but warning when silent renew is used with useRefreshToken but no offline_access scope is given', () => {
|
|
const config = {
|
|
...VALID_CONFIG,
|
|
silentRenew: true,
|
|
useRefreshToken: true,
|
|
scopes: 'scope1 scope2 but_no_offline_access',
|
|
};
|
|
|
|
const loggerSpy = vi.spyOn(loggerService, 'logError');
|
|
const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
|
|
|
|
const result = configValidationService.validateConfig(config);
|
|
|
|
expect(result).toBeTruthy();
|
|
expect(loggerSpy).not.toHaveBeenCalled();
|
|
expect(loggerWarningSpy).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('ensure-no-duplicated-configs.rule', () => {
|
|
it('should print out correct error when mutiple configs with same properties are passed', () => {
|
|
const config1 = {
|
|
...VALID_CONFIG,
|
|
silentRenew: true,
|
|
useRefreshToken: true,
|
|
scopes: 'scope1 scope2 but_no_offline_access',
|
|
};
|
|
const config2 = {
|
|
...VALID_CONFIG,
|
|
silentRenew: true,
|
|
useRefreshToken: true,
|
|
scopes: 'scope1 scope2 but_no_offline_access',
|
|
};
|
|
|
|
const loggerErrorSpy = vi.spyOn(loggerService, 'logError');
|
|
const loggerWarningSpy = vi.spyOn(loggerService, 'logWarning');
|
|
|
|
const result = configValidationService.validateConfigs([
|
|
config1,
|
|
config2,
|
|
]);
|
|
|
|
expect(result).toBeTruthy();
|
|
expect(loggerErrorSpy).not.toHaveBeenCalled();
|
|
expect(vi.mocked(loggerWarningSpy).mock.calls[0]).toEqual([
|
|
config1,
|
|
'You added multiple configs with the same authority, clientId and scope',
|
|
]);
|
|
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 = vi.spyOn(loggerService, 'logWarning');
|
|
|
|
const result = configValidationService.validateConfigs([]);
|
|
|
|
expect(result).toBeFalsy();
|
|
expect(loggerWarningSpy).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('validateConfigs', () => {
|
|
it('calls internal method with empty array if something falsy is passed', () => {
|
|
const spy = vi.spyOn(
|
|
configValidationService as any,
|
|
'validateConfigsInternal'
|
|
);
|
|
|
|
const result = configValidationService.validateConfigs([]);
|
|
|
|
expect(result).toBeFalsy();
|
|
expect(spy).toHaveBeenCalledExactlyOnceWith([], allMultipleConfigRules);
|
|
});
|
|
});
|
|
});
|