fix: fix observable

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

View File

@@ -98,11 +98,9 @@ describe('CodeFlowCallbackHandlerService', () => {
existingIdToken: null,
} as CallbackContext;
service
.codeFlowCallback('test-url', { configId: 'configId1' })
.subscribe((callbackContext) => {
expect(callbackContext).toEqual(expectedCallbackContext);
});
const callbackContext = await lastValueFrom(service
.codeFlowCallback('test-url', { configId: 'configId1' }));
expect(callbackContext).toEqual(expectedCallbackContext);
});
});
@@ -184,16 +182,14 @@ describe('CodeFlowCallbackHandlerService', () => {
'validateStateFromHashCallback'
).mockReturnValue(true);
service
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' })
.subscribe(() => {
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
await lastValueFrom(service
.codeFlowCodeRequest({} as CallbackContext, { configId: 'configId1' }));
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'tokenEndpoint',
undefined,
{ configId: 'configId1' },
expect.any(HttpHeaders)
);
});
});
it('calls url service with custom token params', async () => {
@@ -219,14 +215,12 @@ describe('CodeFlowCallbackHandlerService', () => {
const postSpy = vi.spyOn(dataService, 'post').mockReturnValue(of({}));
service
.codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config)
.subscribe(() => {
expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, {
await lastValueFrom(service
.codeFlowCodeRequest({ code: 'foo' } as CallbackContext, config));
expect(urlServiceSpy).toHaveBeenCalledExactlyOnceWith('foo', config, {
foo: 'bar',
});
expect(postSpy).toHaveBeenCalledTimes(1);
});
});;
expect(postSpy).toHaveBeenCalledTimes(1);
});
it('calls dataService with correct headers if all params are good', async () => {
@@ -247,16 +241,13 @@ describe('CodeFlowCallbackHandlerService', () => {
'validateStateFromHashCallback'
).mockReturnValue(true);
service
.codeFlowCodeRequest({} as CallbackContext, config)
.subscribe(() => {
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe(
await lastValueFrom(service
.codeFlowCodeRequest({} as CallbackContext, config));
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
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', async () => {

View File

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

View File

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

View File

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

View File

@@ -66,24 +66,21 @@ describe('RefreshTokenCallbackHandlerService', () => {
() => ({ tokenEndpoint: 'tokenEndpoint' })
);
service
await lastValueFrom(service
.refreshTokensRequestTokens({} as CallbackContext, {
configId: 'configId1',
})
.subscribe(() => {
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
}));
expect(postSpy).toHaveBeenCalledExactlyOnceWith(
'tokenEndpoint',
undefined,
{ configId: 'configId1' },
expect.any(HttpHeaders)
);
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe(
);;
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
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', async () => {
@@ -95,18 +92,15 @@ describe('RefreshTokenCallbackHandlerService', () => {
() => ({ tokenEndpoint: 'tokenEndpoint' })
);
service
await lastValueFrom(service
.refreshTokensRequestTokens({} as CallbackContext, {
configId: 'configId1',
})
.subscribe(() => {
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;
expect(httpHeaders.has('Content-Type')).toBeTruthy();
expect(httpHeaders.get('Content-Type')).toBe(
}));
const httpHeaders = postSpy.calls.mostRecent().args[3] as HttpHeaders;;
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', async () => {

View File

@@ -69,20 +69,18 @@ describe('StateValidationCallbackHandlerService', () => {
);
const allConfigs = [{ configId: 'configId1' }];
service
const newCallbackContext = await lastValueFrom(service
.callbackStateValidation(
{} as CallbackContext,
allConfigs[0]!,
allConfigs
)
.subscribe((newCallbackContext) => {
expect(newCallbackContext).toEqual({
));
expect(newCallbackContext).toEqual({
validationResult: {
idToken: 'idTokenJustForTesting',
authResponseIsValid: true,
},
} as CallbackContext);
});
});
it('logs error in case of an error', async () => {

View File

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

View File

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