workarounds for jasmine.ajax in unit tests

rebasing develop
This commit is contained in:
Denys Vuika
2024-09-13 13:54:52 -04:00
committed by Anton Ramanovich
parent c4f7fdf093
commit 4d84f665ce
3 changed files with 30 additions and 25 deletions

View File

@@ -17,7 +17,7 @@
import { EventEmitter } from '@angular/core'; import { EventEmitter } from '@angular/core';
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { AppConfigModule, AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core'; import { AppConfigService, AppConfigServiceMock } from '@alfresco/adf-core';
import { UploadService } from './upload.service'; import { UploadService } from './upload.service';
import { RepositoryInfo } from '@alfresco/js-api'; import { RepositoryInfo } from '@alfresco/js-api';
import { BehaviorSubject } from 'rxjs'; import { BehaviorSubject } from 'rxjs';
@@ -26,6 +26,7 @@ import { FileModel, FileUploadStatus } from '../../common/models/file.model';
import { HttpClientTestingModule } from '@angular/common/http/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing';
import { AlfrescoApiService } from '../../services'; import { AlfrescoApiService } from '../../services';
import { AlfrescoApiServiceMock } from '../../mock'; import { AlfrescoApiServiceMock } from '../../mock';
import { AdfHttpClient } from '@alfresco/adf-core/api';
declare let jasmine: any; declare let jasmine: any;
@@ -38,11 +39,13 @@ describe('UploadService', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [AppConfigModule, HttpClientTestingModule], imports: [HttpClientTestingModule],
providers: [ providers: [
UploadService, UploadService,
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }, { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
{ provide: AppConfigService, useClass: AppConfigServiceMock }, { provide: AppConfigService, useClass: AppConfigServiceMock },
// TODO: remove this as soon as unit test not using jasmine.Ajax
{ provide: AdfHttpClient, useValue: null },
{ {
provide: DiscoveryApiService, provide: DiscoveryApiService,
useValue: { useValue: {

View File

@@ -71,10 +71,12 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
ee(this); ee(this);
} }
/** @deprecated not used anywhere */
setDefaultSecurityOption(options: any) { setDefaultSecurityOption(options: any) {
this.defaultSecurityOptions = this.merge(this.defaultSecurityOptions, options); this.defaultSecurityOptions = this.merge(this.defaultSecurityOptions, options);
} }
/** @deprecated not used anywhere */
merge(...objects): any { merge(...objects): any {
const result = {}; const result = {};
@@ -94,9 +96,9 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
} }
request<T = any>(url: string, options?: RequestOptions, sc: SecurityOptions = this.defaultSecurityOptions, emitters?: JsApiEmitters): Promise<T> { request<T = any>(url: string, options?: RequestOptions, sc: SecurityOptions = this.defaultSecurityOptions, emitters?: JsApiEmitters): Promise<T> {
const body = AdfHttpClient.getBody(options); const body = this.getBody(options);
const params = getQueryParamsWithCustomEncoder(options.queryParams, new AlfrescoApiParamEncoder()); const params = getQueryParamsWithCustomEncoder(options.queryParams, new AlfrescoApiParamEncoder());
const responseType = AdfHttpClient.getResponseType(options); const responseType = this.getResponseType(options);
const context = new HttpContext().set(SHOULD_ADD_AUTH_TOKEN, true); const context = new HttpContext().set(SHOULD_ADD_AUTH_TOKEN, true);
const security: SecurityOptions = { ...this.defaultSecurityOptions, ...sc }; const security: SecurityOptions = { ...this.defaultSecurityOptions, ...sc };
const headers = this.getHeaders(options); const headers = this.getHeaders(options);
@@ -135,7 +137,7 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
} }
private addPromiseListeners<T = any>(promise: Promise<T>, eventEmitter: any) { private addPromiseListeners<T = any>(promise: Promise<T>, eventEmitter: any) {
const eventPromise = Object.assign(promise, { return Object.assign(promise, {
on() { on() {
// eslint-disable-next-line prefer-spread, prefer-rest-params // eslint-disable-next-line prefer-spread, prefer-rest-params
eventEmitter.on.apply(eventEmitter, arguments); eventEmitter.on.apply(eventEmitter, arguments);
@@ -157,8 +159,6 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
return this; return this;
} }
}); });
return eventPromise;
} }
private getEventEmitters(): Emitters { private getEventEmitters(): Emitters {
@@ -189,7 +189,7 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
if (isHttpResponseEvent(res)) { if (isHttpResponseEvent(res)) {
eventEmitter.emit('success', res.body); eventEmitter.emit('success', res.body);
return AdfHttpClient.deserialize(res, returnType); return this.deserialize(res, returnType);
} }
}), }),
catchError((err: HttpErrorResponse): Observable<AlfrescoApiResponseError> => { catchError((err: HttpErrorResponse): Observable<AlfrescoApiResponseError> => {
@@ -222,7 +222,7 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
}; };
const alfrescoApiError = new AlfrescoApiResponseError(msg, err.status, error); const alfrescoApiError = new AlfrescoApiResponseError(msg, err.status, error);
return throwError(alfrescoApiError); return throwError(() => alfrescoApiError);
}), }),
takeUntil(abort$) takeUntil(abort$)
) )
@@ -238,8 +238,8 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
return this.addPromiseListeners(promise, eventEmitter); return this.addPromiseListeners(promise, eventEmitter);
} }
private static getBody(options: RequestOptions): any { private getBody(options: RequestOptions): any {
const contentType = options.contentType ? options.contentType : AdfHttpClient.jsonPreferredMime(options.contentTypes); const contentType = options.contentType ? options.contentType : this.jsonPreferredMime(options.contentTypes);
const isFormData = contentType === 'multipart/form-data'; const isFormData = contentType === 'multipart/form-data';
const isFormUrlEncoded = contentType === 'application/x-www-form-urlencoded'; const isFormUrlEncoded = contentType === 'application/x-www-form-urlencoded';
const body = options.bodyParam; const body = options.bodyParam;
@@ -256,8 +256,8 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
} }
private getHeaders(options: RequestOptions): HttpHeaders { private getHeaders(options: RequestOptions): HttpHeaders {
const contentType = options.contentType || AdfHttpClient.jsonPreferredMime(options.contentTypes); const contentType = options.contentType || this.jsonPreferredMime(options.contentTypes);
const accept = options.accept || AdfHttpClient.jsonPreferredMime(options.accepts); const accept = options.accept || this.jsonPreferredMime(options.accepts);
const optionsHeaders = { const optionsHeaders = {
...options.headerParams, ...options.headerParams,
@@ -278,13 +278,13 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
* @param contentTypes a contentType array * @param contentTypes a contentType array
* @returns The chosen content type, preferring JSON. * @returns The chosen content type, preferring JSON.
*/ */
private static jsonPreferredMime(contentTypes: readonly string[]): string { private jsonPreferredMime(contentTypes: readonly string[]): string {
if (!contentTypes?.length) { if (!contentTypes?.length) {
return 'application/json'; return 'application/json';
} }
for (let i = 0; i < contentTypes.length; i++) { for (let i = 0; i < contentTypes.length; i++) {
if (AdfHttpClient.isJsonMime(contentTypes[i])) { if (this.isJsonMime(contentTypes[i])) {
return contentTypes[i]; return contentTypes[i];
} }
} }
@@ -303,7 +303,7 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
* @param contentType The MIME content type to check. * @param contentType The MIME content type to check.
* @returns <code>true</code> if <code>contentType</code> represents JSON, otherwise <code>false</code>. * @returns <code>true</code> if <code>contentType</code> represents JSON, otherwise <code>false</code>.
*/ */
private static isJsonMime(contentType: string): boolean { private isJsonMime(contentType: string): boolean {
return Boolean(contentType?.match(/^application\/json(;.*)?$/i)); return Boolean(contentType?.match(/^application\/json(;.*)?$/i));
} }
@@ -319,16 +319,16 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
} }
private createCSRFToken(a?: any): string { private createCSRFToken(a?: any): string {
const randomValue = AdfHttpClient.getSecureRandomValue(); const randomValue = this.getSecureRandomValue();
return a ? (a ^ ((randomValue * 16) >> (a / 4))).toString(16) : ([1e16] + (1e16).toString()).replace(/[01]/g, this.createCSRFToken); return a ? (a ^ ((randomValue * 16) >> (a / 4))).toString(16) : ([1e16] + (1e16).toString()).replace(/[01]/g, this.createCSRFToken);
} }
private static getSecureRandomValue(): number { private getSecureRandomValue(): number {
const max = Math.pow(2, 32); const max = Math.pow(2, 32);
return window.crypto.getRandomValues(new Uint32Array(1))[0] / max; return window.crypto.getRandomValues(new Uint32Array(1))[0] / max;
} }
private static getResponseType(options: RequestOptions): 'blob' | 'json' | 'text' { private getResponseType(options: RequestOptions): 'blob' | 'json' | 'text' {
const isBlobType = options.returnType?.toString().toLowerCase() === 'blob' || options.responseType?.toString().toLowerCase() === 'blob'; const isBlobType = options.returnType?.toString().toLowerCase() === 'blob' || options.responseType?.toString().toLowerCase() === 'blob';
if (isBlobType) { if (isBlobType) {
@@ -349,7 +349,7 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
* @param returnType return type * @param returnType return type
* @returns deserialized object * @returns deserialized object
*/ */
private static deserialize<T>(response: HttpResponse<T>, returnType?: Constructor<unknown> | 'blob'): any { private deserialize<T>(response: HttpResponse<T>, returnType?: Constructor<unknown> | 'blob'): any {
if (response === null) { if (response === null) {
return null; return null;
} }
@@ -366,7 +366,7 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
} }
if (isBlobResponse(response, returnType)) { if (isBlobResponse(response, returnType)) {
return AdfHttpClient.deserializeBlobResponse(response); return this.deserializeBlobResponse(response);
} }
if (!isConstructor(returnType)) { if (!isConstructor(returnType)) {
@@ -380,7 +380,7 @@ export class AdfHttpClient implements ee.Emitter, JsApiHttpClient {
return new returnType(body); return new returnType(body);
} }
private static deserializeBlobResponse(response: HttpResponse<Blob>) { private deserializeBlobResponse(response: HttpResponse<Blob>) {
return new Blob([response.body], { type: response.headers.get('Content-Type') }); return new Blob([response.body], { type: response.headers.get('Content-Type') });
} }
} }

View File

@@ -17,16 +17,18 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { AppConfigService, AppConfigServiceMock, AuthModule, JWT_STORAGE_SERVICE, NoopTranslateModule, StorageService } from '@alfresco/adf-core'; import { AppConfigService, AppConfigServiceMock, AuthModule, NoopTranslateModule } from '@alfresco/adf-core';
import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-content-services'; import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-content-services';
import { HttpClientTestingModule } from '@angular/common/http/testing'; import { AdfHttpClient } from '@alfresco/adf-core/api';
@NgModule({ @NgModule({
imports: [AuthModule.forRoot({ useHash: true }), NoopAnimationsModule, NoopTranslateModule, HttpClientTestingModule], imports: [AuthModule.forRoot({ useHash: true }), NoopAnimationsModule, NoopTranslateModule, HttpClientTestingModule],
providers: [ providers: [
{ provide: JWT_STORAGE_SERVICE, useClass: StorageService }, { provide: JWT_STORAGE_SERVICE, useClass: StorageService },
{ provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }, { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock },
{ provide: AppConfigService, useClass: AppConfigServiceMock } { provide: AppConfigService, useClass: AppConfigServiceMock },
// TODO: remove this as soon as unit test not using jasmine.Ajax
{ provide: AdfHttpClient, useValue: null }
], ],
exports: [NoopAnimationsModule] exports: [NoopAnimationsModule]
}) })