AAE-35340 Replace deprecated toPromise() usages with firstValueFrom / lastValueFrom (#11161)

This commit is contained in:
Amedeo Lepore
2025-09-03 14:37:13 +02:00
committed by GitHub
parent 93c872b65d
commit 51c55674b4
27 changed files with 178 additions and 191 deletions

View File

@@ -19,7 +19,7 @@ import { SHOULD_ADD_AUTH_TOKEN } from '@alfresco/adf-core/auth';
import { Emitters as JsApiEmitters, HttpClient as JsApiHttpClient } from '@alfresco/js-api';
import { HttpClient, HttpContext, HttpErrorResponse, HttpEvent, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, of, Subject, throwError } from 'rxjs';
import { lastValueFrom, Observable, of, Subject, throwError } from 'rxjs';
import { catchError, map, takeUntil } from 'rxjs/operators';
import {
convertObjectToFormData,
@@ -196,8 +196,8 @@ export class AdfHttpClient implements JsApiHttpClient {
const abort$ = new Subject<void>();
const { eventEmitter, apiClientEmitter } = emitters;
const promise = request$
.pipe(
const promise = lastValueFrom(
request$.pipe(
map((res) => {
if (isHttpUploadProgressEvent(res)) {
const percent = Math.round((res.loaded / res.total) * 100);
@@ -243,7 +243,7 @@ export class AdfHttpClient implements JsApiHttpClient {
}),
takeUntil(abort$)
)
.toPromise();
);
(promise as any).abort = function () {
eventEmitter.emit('abort');

View File

@@ -27,7 +27,7 @@ import {
IdentityJoinGroupRequestModel
} from '../interfaces/identity-user.service.interface';
import { mockIdentityGroups } from './identity-group.mock';
import { Observable, of } from 'rxjs';
import { firstValueFrom, Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { mockAssignedRoles, mockAvailableRoles, mockEffectiveRoles, mockIdentityUser1, mockIdentityUsers } from './identity-user.mock';
@@ -127,7 +127,7 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
async getUsersByRolesWithCurrentUser(roleNames: string[]): Promise<IdentityUserModel[]> {
const filteredUsers: IdentityUserModel[] = [];
if (roleNames && roleNames.length > 0) {
const users = await this.getUsers().toPromise();
const users = await firstValueFrom(this.getUsers());
for (let i = 0; i < users.length; i++) {
const hasAnyRole = await this.userHasAnyRole(users[i].id, roleNames);
@@ -144,7 +144,7 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
const filteredUsers: IdentityUserModel[] = [];
if (roleNames && roleNames.length > 0) {
const currentUser = this.getCurrentUserInfo();
let users = await this.getUsers().toPromise();
let users = await firstValueFrom(this.getUsers());
users = users.filter(({ username }) => username !== currentUser.username);
@@ -160,7 +160,7 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
}
private async userHasAnyRole(userId: string, roleNames: string[]): Promise<boolean> {
const userRoles = await this.getUserRoles(userId).toPromise();
const userRoles = await firstValueFrom(this.getUserRoles(userId));
const hasAnyRole = roleNames.some((roleName) => {
const filteredRoles = userRoles.filter((userRole) => userRole.name.toLocaleLowerCase() === roleName.toLocaleLowerCase());

View File

@@ -17,7 +17,7 @@
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { EMPTY } from 'rxjs';
import { of } from 'rxjs';
import { AppConfigService } from '../../app-config/app-config.service';
import { AUTH_MODULE_CONFIG } from './auth-config';
import { AuthConfigService } from './auth-config.service';
@@ -102,7 +102,7 @@ describe('AuthConfigService', () => {
spyOn<any>(service, 'getLocationOrigin').and.returnValue('http://localhost:3000');
appConfigService = TestBed.inject(AppConfigService);
appConfigService.onLoad = EMPTY;
appConfigService.onLoad = of(true);
});
describe('load auth config using hash', () => {

View File

@@ -21,6 +21,7 @@ import { take } from 'rxjs/operators';
import { AppConfigService } from '../../app-config/app-config.service';
import { AUTH_MODULE_CONFIG, AuthModuleConfig } from './auth-config';
import { OauthConfigModel } from '../models/oauth-config.model';
import { firstValueFrom } from 'rxjs';
/**
* Create auth configuration factory
@@ -36,7 +37,10 @@ export function authConfigFactory(authConfigService: AuthConfigService): Promise
providedIn: 'root'
})
export class AuthConfigService {
constructor(private appConfigService: AppConfigService, @Inject(AUTH_MODULE_CONFIG) private readonly authModuleConfig: AuthModuleConfig) {}
constructor(
private appConfigService: AppConfigService,
@Inject(AUTH_MODULE_CONFIG) private readonly authModuleConfig: AuthModuleConfig
) {}
private _authConfig!: AuthConfig;
get authConfig(): AuthConfig {
@@ -44,7 +48,7 @@ export class AuthConfigService {
}
loadConfig(): Promise<AuthConfig> {
return this.appConfigService.onLoad.pipe(take(1)).toPromise().then(this.loadAppConfig.bind(this));
return firstValueFrom(this.appConfigService.onLoad.pipe(take(1))).then(this.loadAppConfig.bind(this));
}
loadAppConfig(): AuthConfig {

View File

@@ -214,7 +214,7 @@ describe('OidcAuthenticationService shouldPerformSsoLogin', () => {
};
configureTestingModule({ provide: AuthService, useValue: mockAuthServiceValue });
const shouldPerformSsoLogin = await service.shouldPerformSsoLogin$.toPromise();
const shouldPerformSsoLogin = await firstValueFrom(service.shouldPerformSsoLogin$);
expect(shouldPerformSsoLogin).toBeTrue();
});
@@ -225,7 +225,7 @@ describe('OidcAuthenticationService shouldPerformSsoLogin', () => {
};
configureTestingModule({ provide: AuthService, useValue: mockAuthServiceValue });
const shouldPerformSsoLogin = await service.shouldPerformSsoLogin$.toPromise();
const shouldPerformSsoLogin = await firstValueFrom(service.shouldPerformSsoLogin$);
expect(shouldPerformSsoLogin).toBeFalse();
});
@@ -236,7 +236,7 @@ describe('OidcAuthenticationService shouldPerformSsoLogin', () => {
};
configureTestingModule({ provide: AuthService, useValue: mockAuthServiceValue });
const shouldPerformSsoLogin = await service.shouldPerformSsoLogin$.toPromise();
const shouldPerformSsoLogin = await firstValueFrom(service.shouldPerformSsoLogin$);
expect(shouldPerformSsoLogin).toBeFalse();
});
@@ -247,7 +247,7 @@ describe('OidcAuthenticationService shouldPerformSsoLogin', () => {
};
configureTestingModule({ provide: AuthService, useValue: mockAuthServiceValue });
const shouldPerformSsoLogin = await service.shouldPerformSsoLogin$.toPromise();
const shouldPerformSsoLogin = await firstValueFrom(service.shouldPerformSsoLogin$);
expect(shouldPerformSsoLogin).toBeFalse();
});
});

View File

@@ -28,7 +28,7 @@ import {
OAuthSuccessEvent,
OAuthInfoEvent
} from 'angular-oauth2-oidc';
import { of, Subject, timeout } from 'rxjs';
import { firstValueFrom, of, Subject, timeout } from 'rxjs';
import { RedirectAuthService } from './redirect-auth.service';
import { AUTH_MODULE_CONFIG } from './auth-config';
import { RetryLoginService } from './retry-login.service';
@@ -389,8 +389,8 @@ describe('RedirectAuthService', () => {
it('should NOT logout user if the refresh token failed first time', fakeAsync(async () => {
const expectedFakeErrorEvent = new OAuthErrorEvent('token_refresh_error', { reason: 'error' }, {});
const firstEventOccurPromise = service.firstOauthErrorEventOccur$.toPromise();
const secondTokenRefreshErrorEventPromise = service.secondTokenRefreshErrorEventOccur$.pipe(timeout(1000)).toPromise();
const firstEventOccurPromise = firstValueFrom(service.firstOauthErrorEventOccur$);
const secondTokenRefreshErrorEventPromise = firstValueFrom(service.secondTokenRefreshErrorEventOccur$.pipe(timeout(1000)));
oauthEvents$.next(new OAuthErrorEvent('token_refresh_error', { reason: 'error' }, {}));

View File

@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { firstValueFrom, Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { AppConfigService } from '../../app-config/app-config.service';
import { IdentityGroupModel } from '../models/identity-group.model';
@@ -36,7 +36,11 @@ import { OAuth2Service } from './oauth2.service';
providedIn: 'root'
})
export class IdentityUserService implements IdentityUserServiceInterface {
constructor(private jwtHelperService: JwtHelperService, private oAuth2Service: OAuth2Service, private appConfigService: AppConfigService) {}
constructor(
private jwtHelperService: JwtHelperService,
private oAuth2Service: OAuth2Service,
private appConfigService: AppConfigService
) {}
private get identityHost(): string {
return `${this.appConfigService.get('identityHost')}`;
@@ -239,7 +243,7 @@ export class IdentityUserService implements IdentityUserServiceInterface {
async getUsersByRolesWithCurrentUser(roleNames: string[]): Promise<IdentityUserModel[]> {
const filteredUsers: IdentityUserModel[] = [];
if (roleNames && roleNames.length > 0) {
const users = await this.getUsers().toPromise();
const users = await firstValueFrom(this.getUsers());
for (let i = 0; i < users.length; i++) {
const hasAnyRole = await this.userHasAnyRole(users[i].id, roleNames);
@@ -262,7 +266,7 @@ export class IdentityUserService implements IdentityUserServiceInterface {
const filteredUsers: IdentityUserModel[] = [];
if (roleNames && roleNames.length > 0) {
const currentUser = this.getCurrentUserInfo();
let users = await this.getUsers().toPromise();
let users = await firstValueFrom(this.getUsers());
users = users.filter(({ username }) => username !== currentUser.username);
@@ -278,7 +282,7 @@ export class IdentityUserService implements IdentityUserServiceInterface {
}
private async userHasAnyRole(userId: string, roleNames: string[]): Promise<boolean> {
const userRoles = await this.getUserRoles(userId).toPromise();
const userRoles = await firstValueFrom(this.getUserRoles(userId));
const hasAnyRole = roleNames.some((roleName) => {
const filteredRoles = userRoles.filter((userRole) => userRole.name.toLocaleLowerCase() === roleName.toLocaleLowerCase());
@@ -337,7 +341,7 @@ export class IdentityUserService implements IdentityUserServiceInterface {
hasMoreItems: false,
totalItems: totalCount
}
} as IdentityUserQueryResponse)
}) as IdentityUserQueryResponse
)
)
)

View File

@@ -19,6 +19,7 @@ import { HttpClientTestingModule, HttpTestingController } from '@angular/common/
import { TestBed } from '@angular/core/testing';
import { AppConfigService } from '../../app-config/app-config.service';
import { TimeSyncService } from './time-sync.service';
import { firstValueFrom } from 'rxjs';
describe('TimeSyncService', () => {
let service: TimeSyncService;
@@ -30,10 +31,7 @@ describe('TimeSyncService', () => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
TimeSyncService,
{ provide: AppConfigService, useValue: appConfigSpy }
]
providers: [TimeSyncService, { provide: AppConfigService, useValue: appConfigSpy }]
});
service = TestBed.inject(TimeSyncService);
@@ -45,7 +43,6 @@ describe('TimeSyncService', () => {
});
describe('checkTimeSync', () => {
it('should check time sync and return outOfSync as false when time is within allowed skew', () => {
appConfigSpy.get.and.returnValue('http://fake-server-time-url');
@@ -58,15 +55,11 @@ describe('TimeSyncService', () => {
const serverTime = 1728911640000; // (GMT): Monday, October 14, 2024 1:14:00 PM
spyOn(Date, 'now').and.returnValues(
timeBeforeCallingServerTimeEndpoint,
timeResponseReceivedFromServerTimeEndpoint,
localCurrentTime
);
spyOn(Date, 'now').and.returnValues(timeBeforeCallingServerTimeEndpoint, timeResponseReceivedFromServerTimeEndpoint, localCurrentTime);
// difference between localCurrentTime and serverTime is 60 seconds plus the round trip time of 1 second
const allowedClockSkewInSec = 61;
service.checkTimeSync(allowedClockSkewInSec).subscribe(sync => {
service.checkTimeSync(allowedClockSkewInSec).subscribe((sync) => {
expect(sync.outOfSync).toBeFalse();
expect(sync.localDateTimeISO).toEqual('2024-10-14T13:13:00.000Z');
expect(sync.serverDateTimeISO).toEqual('2024-10-14T13:14:00.500Z');
@@ -89,16 +82,12 @@ describe('TimeSyncService', () => {
const serverTime = 1728911640000; // (GMT): Monday, October 14, 2024 1:14:00 PM
spyOn(Date, 'now').and.returnValues(
timeBeforeCallingServerTimeEndpoint,
timeResponseReceivedFromServerTimeEndpoint,
localCurrentTime
);
spyOn(Date, 'now').and.returnValues(timeBeforeCallingServerTimeEndpoint, timeResponseReceivedFromServerTimeEndpoint, localCurrentTime);
// difference between localCurrentTime and serverTime is 60 seconds plus the round trip time of 1 second
// setting allowedClockSkewInSec to 60 seconds will make the local time out of sync
const allowedClockSkewInSec = 60;
service.checkTimeSync(allowedClockSkewInSec).subscribe(sync => {
service.checkTimeSync(allowedClockSkewInSec).subscribe((sync) => {
expect(sync.outOfSync).toBeTrue();
expect(sync.localDateTimeISO).toEqual('2024-10-14T13:13:00.000Z');
expect(sync.serverDateTimeISO).toEqual('2024-10-14T13:14:00.500Z');
@@ -113,12 +102,11 @@ describe('TimeSyncService', () => {
appConfigSpy.get.and.returnValue('');
try {
await service.checkTimeSync(60).toPromise();
await firstValueFrom(service.checkTimeSync(60));
fail('Expected to throw an error');
} catch (error) {
expect(error.message).toBe('serverTimeUrl is not configured.');
}
});
it('should throw an error if the server time endpoint returns an error', () => {
@@ -130,7 +118,7 @@ describe('TimeSyncService', () => {
next: () => {
fail('Expected to throw an error');
},
error: error => {
error: (error) => {
expect(error.message).toBe('Error: Failed to get server time');
}
});
@@ -139,12 +127,10 @@ describe('TimeSyncService', () => {
expect(req.request.method).toBe('GET');
req.error(new ProgressEvent(''));
});
});
describe('isLocalTimeOutOfSync', () => {
it('should return clock is out of sync', () => {
appConfigSpy.get.and.returnValue('http://fake-server-time-url');
const expectedServerTimeUrl = 'http://fake-server-time-url';
@@ -156,16 +142,12 @@ describe('TimeSyncService', () => {
const serverTime = 1728911640000; // (GMT): Monday, October 14, 2024 1:14:00 PM
spyOn(Date, 'now').and.returnValues(
timeBeforeCallingServerTimeEndpoint,
timeResponseReceivedFromServerTimeEndpoint,
localCurrentTime
);
spyOn(Date, 'now').and.returnValues(timeBeforeCallingServerTimeEndpoint, timeResponseReceivedFromServerTimeEndpoint, localCurrentTime);
// difference between localCurrentTime and serverTime is 60 seconds plus the round trip time of 1 second
// setting allowedClockSkewInSec to 60 seconds will make the local time out of sync
const allowedClockSkewInSec = 60;
service.isLocalTimeOutOfSync(allowedClockSkewInSec).subscribe(isOutOfSync => {
service.isLocalTimeOutOfSync(allowedClockSkewInSec).subscribe((isOutOfSync) => {
expect(isOutOfSync).toBeTrue();
});
@@ -186,15 +168,11 @@ describe('TimeSyncService', () => {
const serverTime = 1728911640000; // (GMT): Monday, October 14, 2024 1:14:00 PM
spyOn(Date, 'now').and.returnValues(
timeBeforeCallingServerTimeEndpoint,
timeResponseReceivedFromServerTimeEndpoint,
localCurrentTime
);
spyOn(Date, 'now').and.returnValues(timeBeforeCallingServerTimeEndpoint, timeResponseReceivedFromServerTimeEndpoint, localCurrentTime);
// difference between localCurrentTime and serverTime is 60 seconds plus the round trip time of 1 second
const allowedClockSkewInSec = 61;
service.isLocalTimeOutOfSync(allowedClockSkewInSec).subscribe(isOutOfSync => {
service.isLocalTimeOutOfSync(allowedClockSkewInSec).subscribe((isOutOfSync) => {
expect(isOutOfSync).toBeFalse();
});
@@ -203,6 +181,4 @@ describe('TimeSyncService', () => {
req.flush(serverTime);
});
});
});

View File

@@ -35,6 +35,7 @@ import { UnitTestingUtils } from '../../../testing/unit-testing-utils';
import { HarnessLoader } from '@angular/cdk/testing';
import { ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';
import { provideRouter } from '@angular/router';
import { firstValueFrom } from 'rxjs';
@Component({
selector: 'adf-custom-column-template-component',
@@ -1353,7 +1354,7 @@ describe('DataTable', () => {
expect(rows[1].isSelected).toBeFalsy();
dataTable.resetSelection();
const rowClickPromise = dataTable.rowClick.pipe(take(1)).toPromise();
const rowClickPromise = firstValueFrom(dataTable.rowClick.pipe(take(1)));
testingUtils.clickByCSS('[data-automation-id="datatable-row-0"] > div');
fixture.detectChanges();
await rowClickPromise;
@@ -1363,7 +1364,7 @@ describe('DataTable', () => {
expect(rows2[1].isSelected).toBeFalsy();
dataTable.resetSelection();
const cellClickPromise = dataTable.rowClick.pipe(take(1)).toPromise();
const cellClickPromise = firstValueFrom(dataTable.rowClick.pipe(take(1)));
testingUtils.clickByCSS('[data-automation-id="datatable-row-1"] > div');
fixture.detectChanges();
await cellClickPromise;