refactor: rewrite observable subscribe

This commit is contained in:
master 2025-01-30 21:38:04 +08:00
parent 7ff7e891fc
commit ca5f4984a4
9 changed files with 242 additions and 243 deletions

View File

@ -2,8 +2,9 @@ import {
TestBed, TestBed,
mockImplementationWhenArgsEqual, mockImplementationWhenArgsEqual,
mockRouterProvider, mockRouterProvider,
spyOnProperty,
} from '@/testing'; } from '@/testing';
import { of, throwError } from 'rxjs'; import { lastValueFrom, of, throwError } from 'rxjs';
import { vi } from 'vitest'; import { vi } from 'vitest';
import { AutoLoginService } from '../auto-login/auto-login.service'; import { AutoLoginService } from '../auto-login/auto-login.service';
import { CallbackService } from '../callback/callback.service'; import { CallbackService } from '../callback/callback.service';
@ -108,13 +109,14 @@ describe('CheckAuthService', () => {
); );
const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig'); const spy = vi.spyOn(checkAuthService as any, 'checkAuthWithConfig');
checkAuthService.checkAuth(allConfigs[0]!, allConfigs).subscribe(() => { await lastValueFrom(
expect(spy).toHaveBeenCalledExactlyOnceWith( checkAuthService.checkAuth(allConfigs[0]!, allConfigs)
allConfigs[0]!, );
allConfigs, expect(spy).toHaveBeenCalledExactlyOnceWith(
undefined allConfigs[0]!,
); allConfigs,
}); undefined
);
}); });
it('throws error when url has state param and stored config with matching state param is not found', async () => { it('throws error when url has state param and stored config with matching state param is not found', async () => {
@ -171,7 +173,7 @@ describe('CheckAuthService', () => {
vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue( vi.spyOn(currentUrlService, 'getCurrentUrl').mockReturnValue(
'http://localhost:4200' 'http://localhost:4200'
); );
vi.spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({ spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({
opener: {} as Window, opener: {} as Window,
}); });
vi.spyOn(storagePersistenceService, 'read').mockReturnValue(null); vi.spyOn(storagePersistenceService, 'read').mockReturnValue(null);

View File

@ -1,5 +1,5 @@
import { TestBed, fakeAsync, tick } from '@/testing'; import { TestBed, spyOnProperty } from '@/testing';
import { of, throwError } from 'rxjs'; import { lastValueFrom, of, throwError } from 'rxjs';
import { delay } from 'rxjs/operators'; import { delay } from 'rxjs/operators';
import { vi } from 'vitest'; import { vi } from 'vitest';
import { AuthStateService } from '../auth-state/auth-state.service'; import { AuthStateService } from '../auth-state/auth-state.service';
@ -50,9 +50,6 @@ describe('RefreshSessionService ', () => {
mockProvider(PublicEventsService), mockProvider(PublicEventsService),
], ],
}); });
});
beforeEach(() => {
refreshSessionService = TestBed.inject(RefreshSessionService); refreshSessionService = TestBed.inject(RefreshSessionService);
flowsDataService = TestBed.inject(FlowsDataService); flowsDataService = TestBed.inject(FlowsDataService);
flowHelper = TestBed.inject(FlowHelper); flowHelper = TestBed.inject(FlowHelper);
@ -180,23 +177,24 @@ describe('RefreshSessionService ', () => {
}, },
]; ];
refreshSessionService try {
.userForceRefreshSession(allConfigs[0]!, allConfigs) const result = await lastValueFrom(
.subscribe({ refreshSessionService.userForceRefreshSession(
next: () => { allConfigs[0]!,
fail('It should not return any result.'); allConfigs
}, )
error: (error) => { );
expect(error).toBeInstanceOf(Error); if (result) {
}, expect.fail('It should not return any result.');
complete: () => { } else {
expect( expect(
flowsDataService.resetSilentRenewRunning flowsDataService.resetSilentRenewRunning
).toHaveBeenCalledExactlyOnceWith(allConfigs[0]); ).toHaveBeenCalledExactlyOnceWith(allConfigs[0]);
}, }
}); } catch (error: any) {
expect(error).toBeInstanceOf(Error);
}
}); });
it('should call resetSilentRenewRunning in case of no error', async () => { it('should call resetSilentRenewRunning in case of no error', async () => {
vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue( vi.spyOn(refreshSessionService, 'forceRefreshSession').mockReturnValue(
of({} as LoginResponse) of({} as LoginResponse)
@ -214,7 +212,7 @@ describe('RefreshSessionService ', () => {
.userForceRefreshSession(allConfigs[0]!, allConfigs) .userForceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe({ .subscribe({
error: () => { error: () => {
fail('It should not return any error.'); expect.fail('It should not return any error.');
}, },
complete: () => { complete: () => {
expect( expect(
@ -302,7 +300,7 @@ describe('RefreshSessionService ', () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
true true
); );
vi.spyOnProperty( spyOnProperty(
silentRenewService, silentRenewService,
'refreshSessionWithIFrameCompleted$' 'refreshSessionWithIFrameCompleted$'
).mockReturnValue( ).mockReturnValue(
@ -340,7 +338,7 @@ describe('RefreshSessionService ', () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false false
); );
vi.spyOnProperty( spyOnProperty(
silentRenewService, silentRenewService,
'refreshSessionWithIFrameCompleted$' 'refreshSessionWithIFrameCompleted$'
).mockReturnValue(of(null)); ).mockReturnValue(of(null));
@ -374,7 +372,7 @@ describe('RefreshSessionService ', () => {
refreshSessionService as any, refreshSessionService as any,
'startRefreshSession' 'startRefreshSession'
).mockReturnValue(of(null)); ).mockReturnValue(of(null));
vi.spyOnProperty( spyOnProperty(
silentRenewService, silentRenewService,
'refreshSessionWithIFrameCompleted$' 'refreshSessionWithIFrameCompleted$'
).mockReturnValue(of(null).pipe(delay(11000))); ).mockReturnValue(of(null).pipe(delay(11000)));
@ -395,21 +393,24 @@ describe('RefreshSessionService ', () => {
); );
const expectedInvokeCount = MAX_RETRY_ATTEMPTS; const expectedInvokeCount = MAX_RETRY_ATTEMPTS;
refreshSessionService try {
.forceRefreshSession(allConfigs[0]!, allConfigs) const result = await lastValueFrom(
.subscribe({ refreshSessionService.forceRefreshSession(allConfigs[0]!, allConfigs)
next: () => { );
fail('It should not return any result.');
},
error: (error) => {
expect(error).toBeInstanceOf(Error);
expect(resetSilentRenewRunningSpy).toHaveBeenCalledTimes(
expectedInvokeCount
);
},
});
tick(allConfigs[0].silentRenewTimeoutInSeconds * 10000); if (result) {
expect.fail('It should not return any result.');
}
} catch (error: any) {
expect(error).toBeInstanceOf(Error);
expect(resetSilentRenewRunningSpy).toHaveBeenCalledTimes(
expectedInvokeCount
);
}
await vi.advanceTimersByTimeAsync(
allConfigs[0]!.silentRenewTimeoutInSeconds * 10000
);
}); });
it('occurs unknown error throws it to subscriber', async () => { it('occurs unknown error throws it to subscriber', async () => {
@ -426,7 +427,7 @@ describe('RefreshSessionService ', () => {
flowHelper, flowHelper,
'isCurrentFlowCodeFlowWithRefreshTokens' 'isCurrentFlowCodeFlowWithRefreshTokens'
).mockReturnValue(false); ).mockReturnValue(false);
vi.spyOnProperty( spyOnProperty(
silentRenewService, silentRenewService,
'refreshSessionWithIFrameCompleted$' 'refreshSessionWithIFrameCompleted$'
).mockReturnValue(of(null)); ).mockReturnValue(of(null));
@ -447,7 +448,7 @@ describe('RefreshSessionService ', () => {
.forceRefreshSession(allConfigs[0]!, allConfigs) .forceRefreshSession(allConfigs[0]!, allConfigs)
.subscribe({ .subscribe({
next: () => { next: () => {
fail('It should not return any result.'); expect.fail('It should not return any result.');
}, },
error: (error) => { error: (error) => {
expect(error).toBeInstanceOf(Error); expect(error).toBeInstanceOf(Error);
@ -477,7 +478,7 @@ describe('RefreshSessionService ', () => {
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue( vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
false false
); );
vi.spyOnProperty( spyOnProperty(
silentRenewService, silentRenewService,
'refreshSessionWithIFrameCompleted$' 'refreshSessionWithIFrameCompleted$'
).mockReturnValue(of(null)); ).mockReturnValue(of(null));
@ -512,7 +513,7 @@ describe('RefreshSessionService ', () => {
refreshSessionService as any, refreshSessionService as any,
'startRefreshSession' 'startRefreshSession'
).mockReturnValue(of(null)); ).mockReturnValue(of(null));
vi.spyOnProperty( spyOnProperty(
silentRenewService, silentRenewService,
'refreshSessionWithIFrameCompleted$' 'refreshSessionWithIFrameCompleted$'
).mockReturnValue( ).mockReturnValue(

View File

@ -363,7 +363,7 @@ describe('ParLoginService', () => {
vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue( vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue(
of({} as LoginResponse) of({} as LoginResponse)
); );
vi.spyOnProperty(popupService, 'result$').mockReturnValue( spyOnProperty(popupService, 'result$').mockReturnValue(
of({} as PopupResult) of({} as PopupResult)
); );
const spy = vi.spyOn(popupService, 'openPopUp'); const spy = vi.spyOn(popupService, 'openPopUp');
@ -417,9 +417,7 @@ describe('ParLoginService', () => {
receivedUrl: 'someUrl', receivedUrl: 'someUrl',
}; };
vi.spyOnProperty(popupService, 'result$').mockReturnValue( spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
of(popupResult)
);
service.loginWithPopUpPar(config, allConfigs).subscribe((result) => { service.loginWithPopUpPar(config, allConfigs).subscribe((result) => {
expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith( expect(checkAuthSpy).toHaveBeenCalledExactlyOnceWith(
@ -465,9 +463,7 @@ describe('ParLoginService', () => {
const checkAuthSpy = vi.spyOn(checkAuthService, 'checkAuth'); const checkAuthSpy = vi.spyOn(checkAuthService, 'checkAuth');
const popupResult = { userClosed: true } as PopupResult; const popupResult = { userClosed: true } as PopupResult;
vi.spyOnProperty(popupService, 'result$').mockReturnValue( spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
of(popupResult)
);
service.loginWithPopUpPar(config, allConfigs).subscribe((result) => { service.loginWithPopUpPar(config, allConfigs).subscribe((result) => {
expect(checkAuthSpy).not.toHaveBeenCalled(); expect(checkAuthSpy).not.toHaveBeenCalled();

View File

@ -85,7 +85,7 @@ describe('PopUpLoginService', () => {
authWellKnownService, authWellKnownService,
'queryAndStoreAuthWellKnownEndPoints' 'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({})); ).mockReturnValue(of({}));
vi.spyOnProperty(popupService, 'result$').mockReturnValue( spyOnProperty(popupService, 'result$').mockReturnValue(
of({} as PopupResult) of({} as PopupResult)
); );
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl')); vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
@ -115,7 +115,7 @@ describe('PopUpLoginService', () => {
'queryAndStoreAuthWellKnownEndPoints' 'queryAndStoreAuthWellKnownEndPoints'
).mockReturnValue(of({})); ).mockReturnValue(of({}));
vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl')); vi.spyOn(urlService, 'getAuthorizeUrl').mockReturnValue(of('someUrl'));
vi.spyOnProperty(popupService, 'result$').mockReturnValue( spyOnProperty(popupService, 'result$').mockReturnValue(
of({} as PopupResult) of({} as PopupResult)
); );
vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue( vi.spyOn(checkAuthService, 'checkAuth').mockReturnValue(
@ -162,9 +162,7 @@ describe('PopUpLoginService', () => {
receivedUrl: 'someUrl', receivedUrl: 'someUrl',
}; };
vi.spyOnProperty(popupService, 'result$').mockReturnValue( spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
of(popupResult)
);
popUpLoginService popUpLoginService
.loginWithPopUpStandard(config, [config]) .loginWithPopUpStandard(config, [config])
@ -207,9 +205,7 @@ describe('PopUpLoginService', () => {
.mockReturnValue(of({} as LoginResponse)); .mockReturnValue(of({} as LoginResponse));
const popupResult = { userClosed: true } as PopupResult; const popupResult = { userClosed: true } as PopupResult;
vi.spyOnProperty(popupService, 'result$').mockReturnValue( spyOnProperty(popupService, 'result$').mockReturnValue(of(popupResult));
of(popupResult)
);
popUpLoginService popUpLoginService
.loginWithPopUpStandard(config, [config]) .loginWithPopUpStandard(config, [config])

View File

@ -52,7 +52,7 @@ describe('PopUpService', () => {
vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue( vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue(
false false
); );
vi.spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({ spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({
opener: {} as Window, opener: {} as Window,
}); });
vi.spyOn(storagePersistenceService, 'read').mockReturnValue({ vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
@ -89,7 +89,7 @@ describe('PopUpService', () => {
vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue( vi.spyOn(popUpService as any, 'canAccessSessionStorage').mockReturnValue(
true true
); );
vi.spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({ spyOnProperty(popUpService as any, 'windowInternal').mockReturnValue({
opener: {} as Window, opener: {} as Window,
}); });
vi.spyOn(storagePersistenceService, 'read').mockReturnValue({ vi.spyOn(storagePersistenceService, 'read').mockReturnValue({
@ -271,7 +271,7 @@ describe('PopUpService', () => {
describe('sendMessageToMainWindow', () => { describe('sendMessageToMainWindow', () => {
it('does nothing if window.opener is null', async () => { it('does nothing if window.opener is null', async () => {
// arrange // arrange
vi.spyOnProperty(window, 'opener').mockReturnValue(null); spyOnProperty(window, 'opener').mockReturnValue(null);
const sendMessageSpy = vi.spyOn(popUpService as any, 'sendMessage'); const sendMessageSpy = vi.spyOn(popUpService as any, 'sendMessage');
@ -284,7 +284,7 @@ describe('PopUpService', () => {
it('calls postMessage when window opener is given', async () => { it('calls postMessage when window opener is given', async () => {
// arrange // arrange
vi.spyOnProperty(window, 'opener').mockReturnValue({ spyOnProperty(window, 'opener').mockReturnValue({
postMessage: () => undefined, postMessage: () => undefined,
}); });
const sendMessageSpy = vi.spyOn(window.opener, 'postMessage'); const sendMessageSpy = vi.spyOn(window.opener, 'postMessage');

View File

@ -1,6 +1,6 @@
import { TestBed } from '@/testing'; import { TestBed, spyOnProperty } from '@/testing';
import { Observable, lastValueFrom, of } from 'rxjs'; import { Observable, lastValueFrom, of } from 'rxjs';
import { vi } from 'vitest'; import { type MockInstance, vi } from 'vitest';
import { AuthStateService } from './auth-state/auth-state.service'; import { AuthStateService } from './auth-state/auth-state.service';
import { CheckAuthService } from './auth-state/check-auth.service'; import { CheckAuthService } from './auth-state/check-auth.service';
import { CallbackService } from './callback/callback.service'; import { CallbackService } from './callback/callback.service';
@ -33,8 +33,10 @@ describe('OidcSecurityService', () => {
let userService: UserService; let userService: UserService;
let urlService: UrlService; let urlService: UrlService;
let callbackService: CallbackService; let callbackService: CallbackService;
let authenticatedSpy: jasmine.Spy; let authenticatedSpy: MockInstance<
let userDataSpy: jasmine.Spy; () => (typeof authStateService)['authenticated$']
>;
let userDataSpy: MockInstance<() => (typeof userService)['userData$']>;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -71,14 +73,15 @@ describe('OidcSecurityService', () => {
callbackService = TestBed.inject(CallbackService); callbackService = TestBed.inject(CallbackService);
// this is required because these methods will be invoked by the signal properties when the service is created // this is required because these methods will be invoked by the signal properties when the service is created
authenticatedSpy = vi authenticatedSpy = spyOnProperty(
.spyOnProperty(authStateService, 'authenticated$') authStateService,
.mockReturnValue( 'authenticated$'
of({ isAuthenticated: false, allConfigsAuthenticated: [] }) ).mockReturnValue(
); of({ isAuthenticated: false, allConfigsAuthenticated: [] })
userDataSpy = vi );
.spyOnProperty(userService, 'userData$') userDataSpy = spyOnProperty(userService, 'userData$').mockReturnValue(
.mockReturnValue(of({ userData: null, allUserData: [] })); of({ userData: null, allUserData: [] })
);
oidcSecurityService = TestBed.inject(OidcSecurityService); oidcSecurityService = TestBed.inject(OidcSecurityService);
}); });
@ -88,11 +91,10 @@ describe('OidcSecurityService', () => {
describe('userData$', () => { describe('userData$', () => {
it('calls userService.userData$', async () => { it('calls userService.userData$', async () => {
oidcSecurityService.userData$.subscribe(() => { await lastValueFrom(oidcSecurityService.userData$);
// 1x from this subscribe // 1x from this subscribe
// 1x by the signal property // 1x by the signal property
expect(userDataSpy).toHaveBeenCalledTimes(2); expect(userDataSpy).toHaveBeenCalledTimes(2);
});
}); });
}); });
@ -106,11 +108,10 @@ describe('OidcSecurityService', () => {
describe('isAuthenticated$', () => { describe('isAuthenticated$', () => {
it('calls authStateService.isAuthenticated$', async () => { it('calls authStateService.isAuthenticated$', async () => {
oidcSecurityService.isAuthenticated$.subscribe(() => { await lastValueFrom(oidcSecurityService.isAuthenticated$);
// 1x from this subscribe // 1x from this subscribe
// 1x by the signal property // 1x by the signal property
expect(authenticatedSpy).toHaveBeenCalledTimes(2); expect(authenticatedSpy).toHaveBeenCalledTimes(2);
});
}); });
}); });
@ -126,25 +127,24 @@ describe('OidcSecurityService', () => {
describe('checkSessionChanged$', () => { describe('checkSessionChanged$', () => {
it('calls checkSessionService.checkSessionChanged$', async () => { it('calls checkSessionService.checkSessionChanged$', async () => {
const spy = vi const spy = spyOnProperty(
.spyOnProperty(checkSessionService, 'checkSessionChanged$') checkSessionService,
.mockReturnValue(of(true)); 'checkSessionChanged$'
).mockReturnValue(of(true));
oidcSecurityService.checkSessionChanged$.subscribe(() => { await lastValueFrom(oidcSecurityService.checkSessionChanged$);
expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledTimes(1);
});
}); });
}); });
describe('stsCallback$', () => { describe('stsCallback$', () => {
it('calls callbackService.stsCallback$', async () => { it('calls callbackService.stsCallback$', async () => {
const spy = vi const spy = spyOnProperty(
.spyOnProperty(callbackService, 'stsCallback$') callbackService,
.mockReturnValue(of()); 'stsCallback$'
).mockReturnValue(of());
oidcSecurityService.stsCallback$.subscribe(() => { await lastValueFrom(oidcSecurityService.stsCallback$);
expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledTimes(1);
});
}); });
}); });
@ -159,9 +159,8 @@ describe('OidcSecurityService', () => {
.spyOn(authWellKnownService, 'queryAndStoreAuthWellKnownEndPoints') .spyOn(authWellKnownService, 'queryAndStoreAuthWellKnownEndPoints')
.mockReturnValue(of({})); .mockReturnValue(of({}));
oidcSecurityService.preloadAuthWellKnownDocument().subscribe(() => { await lastValueFrom(oidcSecurityService.preloadAuthWellKnownDocument());
expect(spy).toHaveBeenCalledExactlyOnceWith(config); expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
}); });
}); });
@ -211,9 +210,8 @@ describe('OidcSecurityService', () => {
some: 'thing', some: 'thing',
}); });
oidcSecurityService.getUserData('configId').subscribe(() => { await lastValueFrom(oidcSecurityService.getUserData('configId'));
expect(spy).toHaveBeenCalledExactlyOnceWith(config); expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
}); });
it('returns userdata', async () => { it('returns userdata', async () => {
@ -245,13 +243,8 @@ describe('OidcSecurityService', () => {
.spyOn(checkAuthService, 'checkAuth') .spyOn(checkAuthService, 'checkAuth')
.mockReturnValue(of({} as LoginResponse)); .mockReturnValue(of({} as LoginResponse));
oidcSecurityService.checkAuth().subscribe(() => { await lastValueFrom(oidcSecurityService.checkAuth());
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config], undefined);
config,
[config],
undefined
);
});
}); });
it('calls checkAuthService.checkAuth() with url if one is passed', async () => { it('calls checkAuthService.checkAuth() with url if one is passed', async () => {
@ -265,13 +258,8 @@ describe('OidcSecurityService', () => {
.spyOn(checkAuthService, 'checkAuth') .spyOn(checkAuthService, 'checkAuth')
.mockReturnValue(of({} as LoginResponse)); .mockReturnValue(of({} as LoginResponse));
oidcSecurityService.checkAuth('some-url').subscribe(() => { await lastValueFrom(oidcSecurityService.checkAuth('some-url'));
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config], 'some-url');
config,
[config],
'some-url'
);
});
}); });
}); });
@ -287,9 +275,8 @@ describe('OidcSecurityService', () => {
.spyOn(checkAuthService, 'checkAuthMultiple') .spyOn(checkAuthService, 'checkAuthMultiple')
.mockReturnValue(of([{}] as LoginResponse[])); .mockReturnValue(of([{}] as LoginResponse[]));
oidcSecurityService.checkAuthMultiple().subscribe(() => { await lastValueFrom(oidcSecurityService.checkAuthMultiple());
expect(spy).toHaveBeenCalledExactlyOnceWith([config], undefined); expect(spy).toHaveBeenCalledExactlyOnceWith([config], undefined);
});
}); });
it('calls checkAuthService.checkAuthMultiple() with url if one is passed', async () => { it('calls checkAuthService.checkAuthMultiple() with url if one is passed', async () => {
@ -303,9 +290,8 @@ describe('OidcSecurityService', () => {
.spyOn(checkAuthService, 'checkAuthMultiple') .spyOn(checkAuthService, 'checkAuthMultiple')
.mockReturnValue(of([{}] as LoginResponse[])); .mockReturnValue(of([{}] as LoginResponse[]));
oidcSecurityService.checkAuthMultiple('some-url').subscribe(() => { await lastValueFrom(oidcSecurityService.checkAuthMultiple('some-url'));
expect(spy).toHaveBeenCalledExactlyOnceWith([config], 'some-url'); expect(spy).toHaveBeenCalledExactlyOnceWith([config], 'some-u-+rl');
});
}); });
}); });
@ -321,9 +307,8 @@ describe('OidcSecurityService', () => {
.spyOn(authStateService, 'isAuthenticated') .spyOn(authStateService, 'isAuthenticated')
.mockReturnValue(true); .mockReturnValue(true);
oidcSecurityService.isAuthenticated().subscribe(() => { await lastValueFrom(oidcSecurityService.isAuthenticated());
expect(spy).toHaveBeenCalledExactlyOnceWith(config); expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
}); });
}); });
@ -339,9 +324,8 @@ describe('OidcSecurityService', () => {
.spyOn(checkAuthService, 'checkAuthIncludingServer') .spyOn(checkAuthService, 'checkAuthIncludingServer')
.mockReturnValue(of({} as LoginResponse)); .mockReturnValue(of({} as LoginResponse));
oidcSecurityService.checkAuthIncludingServer().subscribe(() => { await lastValueFrom(oidcSecurityService.checkAuthIncludingServer());
expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config]); expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config]);
});
}); });
}); });
@ -357,9 +341,8 @@ describe('OidcSecurityService', () => {
.spyOn(authStateService, 'getAccessToken') .spyOn(authStateService, 'getAccessToken')
.mockReturnValue(''); .mockReturnValue('');
oidcSecurityService.getAccessToken().subscribe(() => { await lastValueFrom(oidcSecurityService.getAccessToken());
expect(spy).toHaveBeenCalledExactlyOnceWith(config); expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
}); });
}); });
@ -373,9 +356,8 @@ describe('OidcSecurityService', () => {
const spy = vi.spyOn(authStateService, 'getIdToken').mockReturnValue(''); const spy = vi.spyOn(authStateService, 'getIdToken').mockReturnValue('');
oidcSecurityService.getIdToken().subscribe(() => { await lastValueFrom(oidcSecurityService.getIdToken());
expect(spy).toHaveBeenCalledExactlyOnceWith(config); expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
}); });
}); });
@ -390,9 +372,8 @@ describe('OidcSecurityService', () => {
.spyOn(authStateService, 'getRefreshToken') .spyOn(authStateService, 'getRefreshToken')
.mockReturnValue(''); .mockReturnValue('');
oidcSecurityService.getRefreshToken().subscribe(() => { await lastValueFrom(oidcSecurityService.getRefreshToken());
expect(spy).toHaveBeenCalledExactlyOnceWith(config); expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
}); });
}); });
@ -408,9 +389,8 @@ describe('OidcSecurityService', () => {
.spyOn(authStateService, 'getAuthenticationResult') .spyOn(authStateService, 'getAuthenticationResult')
.mockReturnValue(null); .mockReturnValue(null);
oidcSecurityService.getAuthenticationResult().subscribe(() => { await lastValueFrom(oidcSecurityService.getAuthenticationResult());
expect(spy).toHaveBeenCalledExactlyOnceWith(config); expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
}); });
}); });
@ -426,13 +406,8 @@ describe('OidcSecurityService', () => {
.spyOn(tokenHelperService, 'getPayloadFromToken') .spyOn(tokenHelperService, 'getPayloadFromToken')
.mockReturnValue(null); .mockReturnValue(null);
oidcSecurityService.getPayloadFromIdToken().subscribe(() => { await lastValueFrom(oidcSecurityService.getPayloadFromIdToken());
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith('some-token', false, config);
'some-token',
false,
config
);
});
}); });
it('calls `authStateService.getIdToken` method, encode = true', async () => { it('calls `authStateService.getIdToken` method, encode = true', async () => {
@ -446,9 +421,8 @@ describe('OidcSecurityService', () => {
.spyOn(tokenHelperService, 'getPayloadFromToken') .spyOn(tokenHelperService, 'getPayloadFromToken')
.mockReturnValue(null); .mockReturnValue(null);
oidcSecurityService.getPayloadFromIdToken(true).subscribe(() => { await lastValueFrom(oidcSecurityService.getPayloadFromIdToken(true));
expect(spy).toHaveBeenCalledExactlyOnceWith('some-token', true, config); expect(spy).toHaveBeenCalledExactlyOnceWith('some-token', true, config);
});
}); });
}); });
@ -466,13 +440,12 @@ describe('OidcSecurityService', () => {
.spyOn(tokenHelperService, 'getPayloadFromToken') .spyOn(tokenHelperService, 'getPayloadFromToken')
.mockReturnValue(null); .mockReturnValue(null);
oidcSecurityService.getPayloadFromAccessToken().subscribe(() => { await lastValueFrom(oidcSecurityService.getPayloadFromAccessToken());
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(
'some-access-token', 'some-access-token',
false, false,
config config
); );
});
}); });
it('calls `authStateService.getIdToken` method, encode = true', async () => { it('calls `authStateService.getIdToken` method, encode = true', async () => {
@ -488,13 +461,12 @@ describe('OidcSecurityService', () => {
.spyOn(tokenHelperService, 'getPayloadFromToken') .spyOn(tokenHelperService, 'getPayloadFromToken')
.mockReturnValue(null); .mockReturnValue(null);
oidcSecurityService.getPayloadFromAccessToken(true).subscribe(() => { await lastValueFrom(oidcSecurityService.getPayloadFromAccessToken(true));
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(
'some-access-token', 'some-access-token',
true, true,
config config
); );
});
}); });
}); });
@ -507,9 +479,8 @@ describe('OidcSecurityService', () => {
); );
const spy = vi.spyOn(flowsDataService, 'setAuthStateControl'); const spy = vi.spyOn(flowsDataService, 'setAuthStateControl');
oidcSecurityService.setState('anyString').subscribe(() => { await lastValueFrom(oidcSecurityService.setState('anyString'));
expect(spy).toHaveBeenCalledExactlyOnceWith('anyString', config); expect(spy).toHaveBeenCalledExactlyOnceWith('anyString', config);
});
}); });
}); });
@ -522,9 +493,8 @@ describe('OidcSecurityService', () => {
); );
const spy = vi.spyOn(flowsDataService, 'getAuthStateControl'); const spy = vi.spyOn(flowsDataService, 'getAuthStateControl');
oidcSecurityService.getState().subscribe(() => { await lastValueFrom(oidcSecurityService.getState());
expect(spy).toHaveBeenCalledExactlyOnceWith(config); expect(spy).toHaveBeenCalledExactlyOnceWith(config);
});
}); });
}); });
@ -573,14 +543,13 @@ describe('OidcSecurityService', () => {
.spyOn(loginService, 'loginWithPopUp') .spyOn(loginService, 'loginWithPopUp')
.mockImplementation(() => of({} as LoginResponse)); .mockImplementation(() => of({} as LoginResponse));
oidcSecurityService.authorizeWithPopUp().subscribe(() => { await lastValueFrom(oidcSecurityService.authorizeWithPopUp());
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(
config, config,
[config], [config],
undefined, undefined,
undefined undefined
); );
});
}); });
}); });
@ -596,13 +565,8 @@ describe('OidcSecurityService', () => {
.spyOn(refreshSessionService, 'userForceRefreshSession') .spyOn(refreshSessionService, 'userForceRefreshSession')
.mockReturnValue(of({} as LoginResponse)); .mockReturnValue(of({} as LoginResponse));
oidcSecurityService.forceRefreshSession().subscribe(() => { await lastValueFrom(oidcSecurityService.forceRefreshSession());
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config], undefined);
config,
[config],
undefined
);
});
}); });
}); });
@ -617,13 +581,8 @@ describe('OidcSecurityService', () => {
.spyOn(logoffRevocationService, 'logoffAndRevokeTokens') .spyOn(logoffRevocationService, 'logoffAndRevokeTokens')
.mockReturnValue(of(null)); .mockReturnValue(of(null));
oidcSecurityService.logoffAndRevokeTokens().subscribe(() => { await lastValueFrom(oidcSecurityService.logoffAndRevokeTokens());
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config], undefined);
config,
[config],
undefined
);
});
}); });
}); });
@ -638,13 +597,8 @@ describe('OidcSecurityService', () => {
.spyOn(logoffRevocationService, 'logoff') .spyOn(logoffRevocationService, 'logoff')
.mockReturnValue(of(null)); .mockReturnValue(of(null));
oidcSecurityService.logoff().subscribe(() => { await lastValueFrom(oidcSecurityService.logoff());
expect(spy).toHaveBeenCalledExactlyOnceWith( expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config], undefined);
config,
[config],
undefined
);
});
}); });
}); });
@ -656,7 +610,6 @@ describe('OidcSecurityService', () => {
of({ allConfigs: [config], currentConfig: config }) of({ allConfigs: [config], currentConfig: config })
); );
const spy = vi.spyOn(logoffRevocationService, 'logoffLocal'); const spy = vi.spyOn(logoffRevocationService, 'logoffLocal');
await lastValueFrom(oidcSecurityService.logoffLocal()); await lastValueFrom(oidcSecurityService.logoffLocal());
expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config]); expect(spy).toHaveBeenCalledExactlyOnceWith(config, [config]);
}); });
@ -687,9 +640,8 @@ describe('OidcSecurityService', () => {
.spyOn(logoffRevocationService, 'revokeAccessToken') .spyOn(logoffRevocationService, 'revokeAccessToken')
.mockReturnValue(of(null)); .mockReturnValue(of(null));
oidcSecurityService.revokeAccessToken().subscribe(() => { await lastValueFrom(oidcSecurityService.revokeAccessToken());
expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined); expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined);
});
}); });
it('calls logoffRevocationService.revokeAccessToken with accesstoken', async () => { it('calls logoffRevocationService.revokeAccessToken with accesstoken', async () => {
@ -702,9 +654,10 @@ describe('OidcSecurityService', () => {
.spyOn(logoffRevocationService, 'revokeAccessToken') .spyOn(logoffRevocationService, 'revokeAccessToken')
.mockReturnValue(of(null)); .mockReturnValue(of(null));
oidcSecurityService.revokeAccessToken('access_token').subscribe(() => { await lastValueFrom(
expect(spy).toHaveBeenCalledExactlyOnceWith(config, 'access_token'); oidcSecurityService.revokeAccessToken('access_token')
}); );
expect(spy).toHaveBeenCalledExactlyOnceWith(config, 'access_token');
}); });
}); });
@ -719,9 +672,8 @@ describe('OidcSecurityService', () => {
.spyOn(logoffRevocationService, 'revokeRefreshToken') .spyOn(logoffRevocationService, 'revokeRefreshToken')
.mockReturnValue(of(null)); .mockReturnValue(of(null));
oidcSecurityService.revokeRefreshToken().subscribe(() => { await lastValueFrom(oidcSecurityService.revokeRefreshToken());
expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined); expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined);
});
}); });
it('calls logoffRevocationService.revokeRefreshToken with refresh token', async () => { it('calls logoffRevocationService.revokeRefreshToken with refresh token', async () => {
@ -734,9 +686,10 @@ describe('OidcSecurityService', () => {
.spyOn(logoffRevocationService, 'revokeRefreshToken') .spyOn(logoffRevocationService, 'revokeRefreshToken')
.mockReturnValue(of(null)); .mockReturnValue(of(null));
oidcSecurityService.revokeRefreshToken('refresh_token').subscribe(() => { await lastValueFrom(
expect(spy).toHaveBeenCalledExactlyOnceWith(config, 'refresh_token'); oidcSecurityService.revokeRefreshToken('refresh_token')
}); );
expect(spy).toHaveBeenCalledExactlyOnceWith(config, 'refresh_token');
}); });
}); });
@ -752,9 +705,8 @@ describe('OidcSecurityService', () => {
.spyOn(urlService, 'getEndSessionUrl') .spyOn(urlService, 'getEndSessionUrl')
.mockReturnValue(null); .mockReturnValue(null);
oidcSecurityService.getEndSessionUrl().subscribe(() => { await lastValueFrom(oidcSecurityService.getEndSessionUrl());
expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined); expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined);
});
}); });
it('calls logoffRevocationService.getEndSessionUrl with customparams', async () => { it('calls logoffRevocationService.getEndSessionUrl with customparams', async () => {
@ -768,13 +720,12 @@ describe('OidcSecurityService', () => {
.spyOn(urlService, 'getEndSessionUrl') .spyOn(urlService, 'getEndSessionUrl')
.mockReturnValue(null); .mockReturnValue(null);
oidcSecurityService await lastValueFrom(
.getEndSessionUrl({ custom: 'params' }) oidcSecurityService.getEndSessionUrl({ custom: 'params' })
.subscribe(() => { );
expect(spy).toHaveBeenCalledExactlyOnceWith(config, { expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
custom: 'params', custom: 'params',
}); });
});
}); });
}); });
@ -790,9 +741,8 @@ describe('OidcSecurityService', () => {
.spyOn(urlService, 'getAuthorizeUrl') .spyOn(urlService, 'getAuthorizeUrl')
.mockReturnValue(of(null)); .mockReturnValue(of(null));
oidcSecurityService.getAuthorizeUrl().subscribe(() => { await lastValueFrom(oidcSecurityService.getAuthorizeUrl());
expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined); expect(spy).toHaveBeenCalledExactlyOnceWith(config, undefined);
});
}); });
it('calls urlService.getAuthorizeUrl with customparams', async () => { it('calls urlService.getAuthorizeUrl with customparams', async () => {
@ -806,13 +756,12 @@ describe('OidcSecurityService', () => {
.spyOn(urlService, 'getAuthorizeUrl') .spyOn(urlService, 'getAuthorizeUrl')
.mockReturnValue(of(null)); .mockReturnValue(of(null));
oidcSecurityService await lastValueFrom(
.getAuthorizeUrl({ custom: 'params' }) oidcSecurityService.getAuthorizeUrl({ custom: 'params' })
.subscribe(() => { );
expect(spy).toHaveBeenCalledExactlyOnceWith(config, { expect(spy).toHaveBeenCalledExactlyOnceWith(config, {
customParams: { custom: 'params' }, customParams: { custom: 'params' },
}); });
});
}); });
}); });
}); });

View File

@ -2,6 +2,7 @@ export { TestBed } from './testbed';
export { export {
createSpyObj, createSpyObj,
mockImplementationWhenArgsEqual, mockImplementationWhenArgsEqual,
spyOnProperty,
} from './spy'; } from './spy';
export { createRetriableStream } from './create-retriable-stream.helper'; export { createRetriableStream } from './create-retriable-stream.helper';
export { MockRouter, mockRouterProvider } from './router'; export { MockRouter, mockRouterProvider } from './router';

View File

@ -51,3 +51,57 @@ export function mockImplementationWhenArgs<M extends MockInstance<any>>(
return spyImpl?.(...args); return spyImpl?.(...args);
}); });
} }
/**
* mock Jasmine spyOnProperty
*/
export function spyOnProperty<T, K extends keyof T>(
obj: T,
propertyKey: K,
accessType: 'get' | 'set' = 'get',
mockImplementation?: any
) {
const originalDescriptor = Object.getOwnPropertyDescriptor(obj, propertyKey);
if (!originalDescriptor) {
throw new Error(
`Property ${String(propertyKey)} does not exist on the object.`
);
}
const spy = vi.fn();
let value: T[K] | undefined;
if (accessType === 'get') {
Object.defineProperty(obj, propertyKey, {
get: mockImplementation
? () => {
value = mockImplementation();
return value;
}
: spy,
configurable: true,
});
} else if (accessType === 'set') {
Object.defineProperty(obj, propertyKey, {
set: mockImplementation
? (next) => {
value = next;
}
: spy,
configurable: true,
});
}
// 恢复原始属性
spy.mockRestore = () => {
if (originalDescriptor) {
Object.defineProperty(obj, propertyKey, originalDescriptor);
} else {
delete obj[propertyKey];
}
};
return spy;
}

View File

@ -39,7 +39,7 @@ describe('Redirect Service Tests', () => {
}); });
it('redirectTo sets window location href', () => { it('redirectTo sets window location href', () => {
const spy = vi.spyOnProperty(myDocument.location, 'href', 'set'); const spy = spyOnProperty(myDocument.location, 'href', 'set');
service.redirectTo('anyurl'); service.redirectTo('anyurl');
expect(spy).toHaveBeenCalledExactlyOnceWith('anyurl'); expect(spy).toHaveBeenCalledExactlyOnceWith('anyurl');