From 4d4a1dd6b1a10c876c401689a9896bfe98f18d5d Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Wed, 18 Sep 2024 08:05:26 -0400 Subject: [PATCH] ACS-8761 Noop Auth Module for unit testing ergonomics (#10195) --- .../aspect-list-dialog.component.spec.ts | 3 +- .../services/dialog-aspect-list.service.ts | 27 +-- .../content-metadata-card.component.spec.ts | 27 +-- .../content-metadata.component.spec.ts | 21 +-- .../src/lib/testing/content.testing.module.ts | 23 +-- .../alfresco-viewer.component.spec.ts | 118 +++++++------ lib/content-services/src/test.ts | 2 +- .../services/storage-features.service.spec.ts | 11 +- .../lib/services/storage-features.service.ts | 2 +- .../src/lib/app-config/app-config.service.ts | 9 +- .../app-config/debug-app-config.service.ts | 10 +- .../card-view-arrayitem.component.spec.ts | 4 +- .../card-view-dateitem.component.spec.ts | 5 +- .../card-view-dateitem.component.ts | 13 +- ...d-view-keyvaluepairsitem.component.spec.ts | 4 +- .../card-view-mapitem.component.spec.ts | 4 +- .../card-view-selectitem.component.spec.ts | 5 +- .../card-view-textitem.component.spec.ts | 5 +- .../card-view-textitem.component.ts | 4 +- .../card-view/card-view.component.spec.ts | 7 +- .../src/lib/comments/comments.component.ts | 20 +-- .../common/mock/app-config.service.mock.ts | 25 ++- .../services/directionality-config-factory.ts | 29 ---- .../directionality-config.service.spec.ts | 53 ------ .../services/directionality-config.service.ts | 42 ----- .../common/services/storage.service.spec.ts | 63 +++---- .../services/user-preferences.service.spec.ts | 14 +- .../services/user-preferences.service.ts | 50 +++--- .../context-menu-overlay.service.spec.ts | 2 - lib/core/src/lib/core.module.ts | 8 - .../columns-selector.component.spec.ts | 6 +- .../empty-list/empty-list.component.spec.ts | 3 +- .../json-cell/json-cell.component.spec.ts | 3 +- .../json-cell/json-cell.component.ts | 4 +- .../location-cell.component.spec.ts | 18 +- .../data-column/data-column.component.spec.ts | 8 - .../loading-template.directive.spec.ts | 3 +- .../no-content-template.directive.spec.ts | 3 +- .../unsaved-changes.guard.spec.ts | 7 +- .../directives/highlight.directive.spec.ts | 30 ++-- .../lib/directives/logout.directive.spec.ts | 17 +- .../info-drawer/info-drawer.component.spec.ts | 25 ++- .../snackbar-content.component.spec.ts | 15 +- .../empty-content.component.spec.ts | 26 +-- .../src/lib/testing/core.testing.module.ts | 38 +---- lib/core/src/lib/testing/index.ts | 1 + lib/core/src/lib/testing/noop-auth.module.ts | 53 ++++++ .../src/lib/testing/noop-translate.module.ts | 3 +- .../src/lib/toolbar/toolbar.component.spec.ts | 5 +- ...r-container-more-actions.component.mock.ts | 5 +- ...ewer-container-open-with.component.mock.ts | 5 +- ...viewer-container-sidebar.component.mock.ts | 3 +- ...ontainer-toolbar-actions.component.mock.ts | 3 +- ...viewer-container-toolbar.component.mock.ts | 3 +- .../pdf-viewer/pdf-viewer.component.spec.ts | 120 +++++-------- .../viewer-render.component.spec.ts | 13 +- lib/core/test.ts | 2 +- lib/extensions/src/test.ts | 2 +- .../select-apps-dialog.component.spec.ts | 2 +- ...ttach-file-widget-dialog.component.spec.ts | 79 ++++----- .../attach-file-widget-dialog.component.ts | 38 +++-- .../attach-file-widget.component.spec.ts | 4 +- .../people/people.component.spec.ts | 158 ++++++++++-------- .../components/people/people.component.ts | 24 +-- .../process-filters.component.spec.ts | 56 ++----- .../task-details.component.spec.ts | 35 ++-- .../task-details/task-details.component.ts | 9 +- .../src/lib/testing/process.testing.module.ts | 25 +-- lib/process-services/src/test.ts | 2 +- 69 files changed, 630 insertions(+), 836 deletions(-) delete mode 100644 lib/core/src/lib/common/services/directionality-config-factory.ts delete mode 100644 lib/core/src/lib/common/services/directionality-config.service.spec.ts delete mode 100644 lib/core/src/lib/common/services/directionality-config.service.ts create mode 100644 lib/core/src/lib/testing/noop-auth.module.ts diff --git a/lib/content-services/src/lib/aspect-list/aspect-list-dialog.component.spec.ts b/lib/content-services/src/lib/aspect-list/aspect-list-dialog.component.spec.ts index e7e6c2ba47..88254e3c39 100644 --- a/lib/content-services/src/lib/aspect-list/aspect-list-dialog.component.spec.ts +++ b/lib/content-services/src/lib/aspect-list/aspect-list-dialog.component.spec.ts @@ -27,7 +27,6 @@ import { AspectEntry, Node } from '@alfresco/js-api'; import { NodesApiService } from '../common/services/nodes-api.service'; import { By } from '@angular/platform-browser'; import { AspectListComponent } from './aspect-list.component'; -import { HttpClientTestingModule } from '@angular/common/http/testing'; const aspectListMock: AspectEntry[] = [ { @@ -114,7 +113,7 @@ describe('AspectListDialogComponent', () => { excludedAspects: [] }; await TestBed.configureTestingModule({ - imports: [HttpClientTestingModule, ContentTestingModule, MatDialogModule], + imports: [ContentTestingModule, MatDialogModule], providers: [ { provide: MAT_DIALOG_DATA, useValue: data }, { diff --git a/lib/content-services/src/lib/aspect-list/services/dialog-aspect-list.service.ts b/lib/content-services/src/lib/aspect-list/services/dialog-aspect-list.service.ts index 8c4cec941c..8ed071a414 100644 --- a/lib/content-services/src/lib/aspect-list/services/dialog-aspect-list.service.ts +++ b/lib/content-services/src/lib/aspect-list/services/dialog-aspect-list.service.ts @@ -28,7 +28,6 @@ import { CategoryService } from '../../category'; providedIn: 'root' }) export class DialogAspectListService { - constructor( private dialog: MatDialog, private overlayContainer: OverlayContainer, @@ -49,8 +48,8 @@ export class DialogAspectListService { select, nodeId, excludedAspects: [ - ...this.tagService.areTagsEnabled() ? [] : ['cm:taggable'], - ...this.categoryService.areCategoriesEnabled() ? [] : ['cm:generalclassifiable'] + ...(this.tagService.areTagsEnabled() ? [] : ['cm:taggable']), + ...(this.categoryService.areCategoriesEnabled() ? [] : ['cm:generalclassifiable']) ] }; @@ -58,15 +57,17 @@ export class DialogAspectListService { return select; } - private openDialog(data: AspectListDialogComponentData, panelClass: string, width: string, - selectorAutoFocusedOnClose?: string) { - this.dialog.open(AspectListDialogComponent, { - data, - panelClass, - width, - role: 'dialog', - disableClose: true - }).afterClosed().subscribe(() => this.focusOnClose(selectorAutoFocusedOnClose)); + private openDialog(data: AspectListDialogComponentData, panelClass: string, width: string, selectorAutoFocusedOnClose?: string) { + this.dialog + .open(AspectListDialogComponent, { + data, + panelClass, + width, + role: 'dialog', + disableClose: true + }) + .afterClosed() + .subscribe(() => this.focusOnClose(selectorAutoFocusedOnClose)); this.overlayContainer.getContainerElement().setAttribute('role', 'main'); } @@ -77,7 +78,7 @@ export class DialogAspectListService { private focusOnClose(selectorAutoFocusedOnClose: string): void { if (selectorAutoFocusedOnClose) { - document.querySelector(selectorAutoFocusedOnClose).focus(); + document.querySelector(selectorAutoFocusedOnClose)?.focus(); } } } diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts index 6eb989d9e3..d97123b49c 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata-card/content-metadata-card.component.spec.ts @@ -20,22 +20,17 @@ import { By } from '@angular/platform-browser'; import { Node } from '@alfresco/js-api'; import { ContentMetadataCardComponent } from './content-metadata-card.component'; import { ContentMetadataComponent } from '../content-metadata/content-metadata.component'; -import { APP_INITIALIZER, SimpleChange } from '@angular/core'; +import { SimpleChange } from '@angular/core'; import { NodeAspectService } from '../../../aspect-list/services/node-aspect.service'; import { ContentMetadataService } from '../../services/content-metadata.service'; import { AllowableOperationsEnum } from '../../../common/models/allowable-operations.enum'; import { of } from 'rxjs'; -import { AuthModule, NoopTranslateModule } from '@alfresco/adf-core'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { versionCompatibilityFactory } from '../../../version-compatibility/version-compatibility-factory'; -import { VersionCompatibilityService } from '../../../version-compatibility'; import { MatDialogModule } from '@angular/material/dialog'; import { MatSnackBarModule } from '@angular/material/snack-bar'; import { CategoryService } from '../../../category'; import { TagService } from '../../../tag'; import { PropertyDescriptorsService } from '../../public-api'; -import { AlfrescoApiService } from '../../../services/alfresco-api.service'; -import { AlfrescoApiServiceMock } from '../../../mock/alfresco-api.service.mock'; +import { ContentTestingModule } from '../../../testing/content.testing.module'; describe('ContentMetadataCardComponent', () => { let component: ContentMetadataCardComponent; @@ -52,23 +47,7 @@ describe('ContentMetadataCardComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - NoopTranslateModule, - AuthModule.forRoot({ useHash: true }), - MatDialogModule, - MatSnackBarModule, - ContentMetadataCardComponent - ], - providers: [ - { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }, - { - provide: APP_INITIALIZER, - useFactory: versionCompatibilityFactory, - deps: [VersionCompatibilityService], - multi: true - } - ] + imports: [ContentTestingModule, MatDialogModule, MatSnackBarModule, ContentMetadataCardComponent] }); fixture = TestBed.createComponent(ContentMetadataCardComponent); contentMetadataService = TestBed.inject(ContentMetadataService); diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts index 0a88874256..90c60aacbb 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts @@ -21,22 +21,13 @@ import { By } from '@angular/platform-browser'; import { Category, CategoryPaging, ClassesApi, Node, Tag, TagBody, TagEntry, TagPaging, TagPagingList } from '@alfresco/js-api'; import { ContentMetadataComponent } from './content-metadata.component'; import { ContentMetadataService } from '../../services/content-metadata.service'; -import { - AppConfigService, - AuthModule, - CardViewBaseItemModel, - CardViewComponent, - NoopTranslateModule, - NotificationService, - UpdateNotification -} from '@alfresco/adf-core'; +import { AppConfigService, CardViewBaseItemModel, CardViewComponent, NotificationService, UpdateNotification } from '@alfresco/adf-core'; import { NodesApiService } from '../../../common/services/nodes-api.service'; import { EMPTY, of, throwError } from 'rxjs'; import { CardViewContentUpdateService } from '../../../common/services/card-view-content-update.service'; import { PropertyGroup } from '../../interfaces/property-group.interface'; import { PropertyDescriptorsService } from '../../services/property-descriptors.service'; import { MatExpansionPanel } from '@angular/material/expansion'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { MatDialogModule } from '@angular/material/dialog'; import { MatSnackBarModule } from '@angular/material/snack-bar'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; @@ -45,6 +36,7 @@ import { TagService } from '../../../tag/services/tag.service'; import { CategoryService } from '../../../category/services/category.service'; import { TagsCreatorComponent, TagsCreatorMode } from '../../../tag'; import { CategoriesManagementComponent, CategoriesManagementMode } from '../../../category'; +import { ContentTestingModule } from '../../../testing/content.testing.module'; describe('ContentMetadataComponent', () => { let component: ContentMetadataComponent; @@ -176,14 +168,7 @@ describe('ContentMetadataComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - NoopTranslateModule, - AuthModule.forRoot({ useHash: true }), - MatDialogModule, - MatSnackBarModule, - ContentMetadataComponent - ], + imports: [ContentTestingModule, MatDialogModule, MatSnackBarModule, ContentMetadataComponent], providers: [ { provide: TagService, diff --git a/lib/content-services/src/lib/testing/content.testing.module.ts b/lib/content-services/src/lib/testing/content.testing.module.ts index 87a0c2bd01..140a130ee5 100644 --- a/lib/content-services/src/lib/testing/content.testing.module.ts +++ b/lib/content-services/src/lib/testing/content.testing.module.ts @@ -17,16 +17,7 @@ import { NgModule, APP_INITIALIZER } from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { RouterTestingModule } from '@angular/router/testing'; -import { - CoreModule, - AppConfigService, - CookieService, - AppConfigServiceMock, - CookieServiceMock, - AuthModule, - NoopTranslateModule -} from '@alfresco/adf-core'; +import { CoreModule, NoopTranslateModule, NoopAuthModule } from '@alfresco/adf-core'; import { ContentModule } from '../content.module'; import { versionCompatibilityFactory } from '../version-compatibility/version-compatibility-factory'; import { AlfrescoApiService } from '../services/alfresco-api.service'; @@ -35,19 +26,9 @@ import { MatIconTestingModule } from '@angular/material/icon/testing'; import { AlfrescoApiServiceMock } from '../mock'; @NgModule({ - imports: [ - AuthModule.forRoot({ useHash: true }), - NoopAnimationsModule, - RouterTestingModule, - CoreModule, - NoopTranslateModule, - ContentModule, - MatIconTestingModule - ], + imports: [NoopAnimationsModule, CoreModule, NoopAuthModule, NoopTranslateModule, ContentModule, MatIconTestingModule], providers: [ { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }, - { provide: AppConfigService, useClass: AppConfigServiceMock }, - { provide: CookieService, useClass: CookieServiceMock }, { provide: APP_INITIALIZER, useFactory: versionCompatibilityFactory, diff --git a/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.spec.ts b/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.spec.ts index a7c7e2f5da..ebde019ac3 100644 --- a/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.spec.ts +++ b/lib/content-services/src/lib/viewer/components/alfresco-viewer.component.spec.ts @@ -21,29 +21,40 @@ import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testin import { MatDialog, MatDialogModule } from '@angular/material/dialog'; import { AppExtensionService, ViewerExtensionRef } from '@alfresco/adf-extensions'; import { ContentInfo, Node, NodeEntry, VersionEntry } from '@alfresco/js-api'; -import { AlfrescoViewerComponent, ContentService, NodeActionsService, RenditionService } from '@alfresco/adf-content-services'; import { - AuthModule, CloseButtonPosition, EventMock, ViewUtilService, ViewerComponent, VIEWER_DIRECTIVES, ViewerSidebarComponent, - NoopTranslateModule + NoopTranslateModule, + ViewerToolbarComponent, + ViewerOpenWithComponent, + ViewerMoreActionsComponent, + ViewerToolbarActionsComponent, + NoopAuthModule } from '@alfresco/adf-core'; import { NodesApiService } from '../../common/services/nodes-api.service'; import { UploadService } from '../../common/services/upload.service'; import { FileModel } from '../../common/models/file.model'; import { throwError } from 'rxjs'; -import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { Component } from '@angular/core'; import { ESCAPE } from '@angular/cdk/keycodes'; import { By } from '@angular/platform-browser'; -import { AlfrescoApiService } from '../../services'; -import { AlfrescoApiServiceMock } from '../../mock'; +import { MatIconModule } from '@angular/material/icon'; +import { MatMenuModule } from '@angular/material/menu'; +import { MatButtonModule } from '@angular/material/button'; +import { AlfrescoViewerComponent } from './alfresco-viewer.component'; +import { RenditionService } from '../../common/services/rendition.service'; +import { NodeActionsService } from '../../document-list/services/node-actions.service'; +import { ContentTestingModule } from '../../testing/content.testing.module'; +import { ContentService } from '../../common/services/content.service'; @Component({ selector: 'adf-viewer-container-toolbar', + standalone: true, + imports: [ViewerToolbarComponent, AlfrescoViewerComponent], template: ` @@ -56,22 +67,24 @@ class ViewerWithCustomToolbarComponent {} @Component({ selector: 'adf-viewer-container-toolbar-actions', - template: ` - - - - - - ` + standalone: true, + imports: [MatIconModule, MatButtonModule, ViewerToolbarActionsComponent, AlfrescoViewerComponent], + template: ` + + + + ` }) class ViewerWithCustomToolbarActionsComponent {} @Component({ selector: 'adf-viewer-container-sidebar', + standalone: true, + imports: [ViewerSidebarComponent, AlfrescoViewerComponent], template: ` - +
@@ -88,6 +101,8 @@ class DummyDialogComponent {} @Component({ selector: 'adf-viewer-container-open-with', + standalone: true, + imports: [MatIconModule, MatMenuModule, ViewerOpenWithComponent, AlfrescoViewerComponent], template: ` @@ -111,24 +126,24 @@ class ViewerWithCustomOpenWithComponent {} @Component({ selector: 'adf-viewer-container-more-actions', - template: ` - - - - - - - - ` + standalone: true, + imports: [MatIconModule, MatMenuModule, ViewerMoreActionsComponent, AlfrescoViewerComponent], + template: ` + + + + + + ` }) class ViewerWithCustomMoreActionsComponent {} @@ -147,8 +162,12 @@ describe('AlfrescoViewerComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [AuthModule.forRoot({ useHash: true }), MatDialogModule, NoopTranslateModule, ...VIEWER_DIRECTIVES], - declarations: [ + imports: [ + ContentTestingModule, + NoopAuthModule, + MatDialogModule, + NoopTranslateModule, + ...VIEWER_DIRECTIVES, ViewerWithCustomToolbarComponent, ViewerWithCustomSidebarComponent, ViewerWithCustomOpenWithComponent, @@ -157,19 +176,16 @@ describe('AlfrescoViewerComponent', () => { ], providers: [ ContentService, - { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }, { provide: RenditionService, useValue: { - getNodeRendition: () => throwError('thrown'), + getNodeRendition: () => throwError(() => new Error('thrown')), generateMediaTracksRendition: () => {} } }, { provide: Location, useClass: SpyLocation }, - MatDialog, - ViewerSidebarComponent - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + MatDialog + ] }); fixture = TestBed.createComponent(AlfrescoViewerComponent); element = fixture.nativeElement; @@ -380,33 +396,39 @@ describe('AlfrescoViewerComponent', () => { }); }); - it('should stop propagation on sidebar keydown event [keydown]', fakeAsync(() => { + it('should stop propagation on sidebar keydown event [keydown]', async () => { const customFixture = TestBed.createComponent(ViewerWithCustomSidebarComponent); const customElement: HTMLElement = customFixture.nativeElement; const escapeKeyboardEvent = new KeyboardEvent('keydown', { key: ESCAPE.toString() }); const stopPropagationSpy = spyOn(escapeKeyboardEvent, 'stopPropagation'); customFixture.detectChanges(); - const viewerSidebarElement = customElement.querySelector('adf-viewer-sidebar'); + await customFixture.whenStable(); + + const viewerSidebarElement = customElement.querySelector('.adf-viewer-sidebar'); viewerSidebarElement.dispatchEvent(escapeKeyboardEvent); + customFixture.detectChanges(); expect(stopPropagationSpy).toHaveBeenCalled(); - })); + }); - it('should stop propagation on sidebar keyup event [keyup]', fakeAsync(() => { + it('should stop propagation on sidebar keyup event [keyup]', async () => { const customFixture = TestBed.createComponent(ViewerWithCustomSidebarComponent); const customElement: HTMLElement = customFixture.nativeElement; const escapeKeyboardEvent = new KeyboardEvent('keyup', { key: ESCAPE.toString() }); const stopPropagationSpy = spyOn(escapeKeyboardEvent, 'stopPropagation'); customFixture.detectChanges(); - const viewerSidebarElement = customElement.querySelector('adf-viewer-sidebar'); + await customFixture.whenStable(); + + const viewerSidebarElement = customElement.querySelector('.adf-viewer-sidebar'); viewerSidebarElement.dispatchEvent(escapeKeyboardEvent); + await customFixture.whenStable(); expect(stopPropagationSpy).toHaveBeenCalled(); - })); + }); }); describe('error handling', () => { diff --git a/lib/content-services/src/test.ts b/lib/content-services/src/test.ts index 0b428a1749..b0b8672388 100644 --- a/lib/content-services/src/test.ts +++ b/lib/content-services/src/test.ts @@ -22,7 +22,7 @@ import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@ang // First, initialize the Angular testing environment. getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { - teardown: { destroyAfterEach: false } + teardown: { destroyAfterEach: true } }); declare const pdfjsLib: any; diff --git a/lib/core/feature-flags/src/lib/services/storage-features.service.spec.ts b/lib/core/feature-flags/src/lib/services/storage-features.service.spec.ts index 62085a23ca..b2322ac458 100644 --- a/lib/core/feature-flags/src/lib/services/storage-features.service.spec.ts +++ b/lib/core/feature-flags/src/lib/services/storage-features.service.spec.ts @@ -17,7 +17,7 @@ import { TestBed } from '@angular/core/testing'; import { StorageFeaturesService } from './storage-features.service'; -import { CoreTestingModule, StorageService } from '../../../../src/public-api'; +import { StorageService } from '../../../../src/public-api'; import { FlagSet, WritableFeaturesServiceConfigToken } from '../interfaces/features.interface'; import { skip, take } from 'rxjs/operators'; @@ -41,7 +41,6 @@ describe('StorageFeaturesService', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], providers: [ { provide: StorageService, useValue: mockStorage }, { @@ -49,8 +48,7 @@ describe('StorageFeaturesService', () => { useValue: { storageKey: 'storage-key-test' } - }, - StorageFeaturesService + } ] }); @@ -170,11 +168,6 @@ describe('StorageFeaturesService', () => { describe('if flags are not present in LocalStorage and no configuration is provided', () => { beforeEach(() => { - TestBed.configureTestingModule({ - imports: [CoreTestingModule], - providers: [StorageFeaturesService] - }); - storageFeaturesService = TestBed.inject(StorageFeaturesService); }); diff --git a/lib/core/feature-flags/src/lib/services/storage-features.service.ts b/lib/core/feature-flags/src/lib/services/storage-features.service.ts index 809da22d94..4f1ddd5b02 100644 --- a/lib/core/feature-flags/src/lib/services/storage-features.service.ts +++ b/lib/core/feature-flags/src/lib/services/storage-features.service.ts @@ -30,7 +30,7 @@ import { import { FlagSetParser } from './flagset.parser'; import { StorageService } from '@alfresco/adf-core'; -@Injectable() +@Injectable({ providedIn: 'root' }) export class StorageFeaturesService implements IFeaturesService, IWritableFeaturesService { private currentFlagState: WritableFlagChangeset = {}; private flags = new BehaviorSubject({}); diff --git a/lib/core/src/lib/app-config/app-config.service.ts b/lib/core/src/lib/app-config/app-config.service.ts index 1efe6a50fa..a2343d9b5c 100644 --- a/lib/core/src/lib/app-config/app-config.service.ts +++ b/lib/core/src/lib/app-config/app-config.service.ts @@ -16,7 +16,7 @@ */ import { HttpClient } from '@angular/common/http'; -import { Injectable } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { ObjectUtils } from '../common/utils/object-utils'; import { Observable, ReplaySubject } from 'rxjs'; import { map, distinctUntilChanged, take } from 'rxjs/operators'; @@ -63,6 +63,9 @@ export enum Status { providedIn: 'root' }) export class AppConfigService { + protected http = inject(HttpClient); + protected extensionService = inject(ExtensionService); + config: any = { application: { name: 'Alfresco ADF Application' @@ -80,11 +83,11 @@ export class AppConfigService { return this.status === Status.LOADED; } - constructor(protected http: HttpClient, protected extensionService: ExtensionService) { + constructor() { this.onLoadSubject = new ReplaySubject(); this.onLoad = this.onLoadSubject.asObservable(); - extensionService.setup$.subscribe((config) => { + this.extensionService.setup$.subscribe((config) => { this.onExtensionsLoaded(config); }); } diff --git a/lib/core/src/lib/app-config/debug-app-config.service.ts b/lib/core/src/lib/app-config/debug-app-config.service.ts index 30959ea875..56ace1ab36 100644 --- a/lib/core/src/lib/app-config/debug-app-config.service.ts +++ b/lib/core/src/lib/app-config/debug-app-config.service.ts @@ -16,25 +16,23 @@ */ import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; import { StorageService } from '../common/services/storage.service'; import { AppConfigService, AppConfigValues } from './app-config.service'; -import { ExtensionService } from '@alfresco/adf-extensions'; @Injectable() export class DebugAppConfigService extends AppConfigService { - constructor(private storage: StorageService, http: HttpClient, extensionService: ExtensionService) { - super(http, extensionService); + constructor(private storage: StorageService) { + super(); } /** @override */ get(key: string, defaultValue?: T): T { if (key === AppConfigValues.OAUTHCONFIG) { - return (JSON.parse(this.storage.getItem(key)) || super.get(key, defaultValue)); + return JSON.parse(this.storage.getItem(key)) || super.get(key, defaultValue); } else if (key === AppConfigValues.APPLICATION) { return undefined; } else { - return (this.storage.getItem(key) as any || super.get(key, defaultValue)); + return (this.storage.getItem(key) as any) || super.get(key, defaultValue); } } } diff --git a/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.spec.ts index df30c3032e..b5e2b72c41 100644 --- a/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-arrayitem/card-view-arrayitem.component.spec.ts @@ -26,7 +26,7 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatChipHarness, MatChipListboxHarness } from '@angular/material/chips/testing'; import { MatButtonHarness } from '@angular/material/button/testing'; import { MatIconHarness } from '@angular/material/icon/testing'; -import { CoreTestingModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '@alfresco/adf-core'; describe('CardViewArrayItemComponent', () => { let loader: HarnessLoader; @@ -51,7 +51,7 @@ describe('CardViewArrayItemComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, CardViewArrayItemComponent] + imports: [NoopTranslateModule, CardViewArrayItemComponent] }); fixture = TestBed.createComponent(CardViewArrayItemComponent); service = TestBed.inject(CardViewUpdateService); diff --git a/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts index e58386874e..f5daee6349 100644 --- a/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.spec.ts @@ -28,8 +28,7 @@ import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatChipHarness } from '@angular/material/chips/testing'; import { addMinutes } from 'date-fns'; -import { MatSnackBarModule } from '@angular/material/snack-bar'; -import { CoreTestingModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '@alfresco/adf-core'; describe('CardViewDateItemComponent', () => { let loader: HarnessLoader; @@ -39,7 +38,7 @@ describe('CardViewDateItemComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, MatSnackBarModule, CardViewDateItemComponent] + imports: [NoopTranslateModule, CardViewDateItemComponent] }); appConfigService = TestBed.inject(AppConfigService); appConfigService.config.dateValues = { diff --git a/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.ts b/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.ts index a5f229b6eb..09e236e1a7 100644 --- a/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.ts +++ b/lib/core/src/lib/card-view/components/card-view-dateitem/card-view-dateitem.component.ts @@ -39,6 +39,8 @@ import { TranslateModule } from '@ngx-translate/core'; import { MatIconModule } from '@angular/material/icon'; import { MatChipsModule } from '@angular/material/chips'; import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; @Component({ providers: [ @@ -49,7 +51,16 @@ import { MatFormFieldModule } from '@angular/material/form-field'; ], selector: 'adf-card-view-dateitem', standalone: true, - imports: [CommonModule, TranslateModule, MatIconModule, MatDatetimepickerModule, MatChipsModule, MatFormFieldModule], + imports: [ + CommonModule, + TranslateModule, + MatIconModule, + MatDatetimepickerModule, + MatChipsModule, + MatFormFieldModule, + MatDatepickerModule, + MatSnackBarModule + ], templateUrl: './card-view-dateitem.component.html', styleUrls: ['./card-view-dateitem.component.scss'], encapsulation: ViewEncapsulation.None, diff --git a/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts index efded0fb22..2713b8f331 100644 --- a/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts @@ -20,7 +20,7 @@ import { By } from '@angular/platform-browser'; import { CardViewKeyValuePairsItemModel } from '../../models/card-view-keyvaluepairs.model'; import { CardViewKeyValuePairsItemComponent } from './card-view-keyvaluepairsitem.component'; import { CardViewUpdateService } from '../../services/card-view-update.service'; -import { CoreTestingModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '@alfresco/adf-core'; describe('CardViewKeyValuePairsItemComponent', () => { let fixture: ComponentFixture; @@ -31,7 +31,7 @@ describe('CardViewKeyValuePairsItemComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, CardViewKeyValuePairsItemComponent] + imports: [NoopTranslateModule, CardViewKeyValuePairsItemComponent] }); fixture = TestBed.createComponent(CardViewKeyValuePairsItemComponent); cardViewUpdateService = TestBed.inject(CardViewUpdateService); diff --git a/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts index cbff08b5ef..9fdd627cd4 100644 --- a/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-mapitem/card-view-mapitem.component.spec.ts @@ -21,7 +21,7 @@ import { By } from '@angular/platform-browser'; import { CardViewMapItemModel } from '../../models/card-view-mapitem.model'; import { CardViewUpdateService } from '../../services/card-view-update.service'; import { CardViewMapItemComponent } from './card-view-mapitem.component'; -import { CoreTestingModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '@alfresco/adf-core'; describe('CardViewMapItemComponent', () => { let service: CardViewUpdateService; @@ -33,7 +33,7 @@ describe('CardViewMapItemComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, CardViewMapItemComponent] + imports: [NoopTranslateModule, CardViewMapItemComponent] }); fixture = TestBed.createComponent(CardViewMapItemComponent); service = TestBed.inject(CardViewUpdateService); diff --git a/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.spec.ts index bcfd113a4c..e735b89ac3 100644 --- a/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-selectitem/card-view-selectitem.component.spec.ts @@ -25,7 +25,8 @@ import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatSelectHarness } from '@angular/material/select/testing'; import { MatFormFieldHarness } from '@angular/material/form-field/testing'; -import { CoreTestingModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('CardViewSelectItemComponent', () => { let loader: HarnessLoader; @@ -59,7 +60,7 @@ describe('CardViewSelectItemComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, CardViewSelectItemComponent] + imports: [NoopTranslateModule, NoopAnimationsModule, CardViewSelectItemComponent] }); fixture = TestBed.createComponent(CardViewSelectItemComponent); component = fixture.componentInstance; diff --git a/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts b/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts index d172bbf84d..2f9002595f 100644 --- a/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.spec.ts @@ -20,7 +20,6 @@ import { By } from '@angular/platform-browser'; import { CardViewTextItemModel } from '../../models/card-view-textitem.model'; import { CardViewUpdateService } from '../../services/card-view-update.service'; import { CardViewTextItemComponent } from './card-view-textitem.component'; -import { CoreTestingModule } from '../../../testing/core.testing.module'; import { CardViewItemFloatValidator } from '../../validators/card-view-item-float.validator'; import { CardViewItemIntValidator } from '../../validators/card-view-item-int.validator'; import { CardViewIntItemModel } from '../../models/card-view-intitem.model'; @@ -33,6 +32,8 @@ import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatChipHarness, MatChipGridHarness } from '@angular/material/chips/testing'; import { MatInputHarness } from '@angular/material/input/testing'; +import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('CardViewTextItemComponent', () => { let loader: HarnessLoader; @@ -111,7 +112,7 @@ describe('CardViewTextItemComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, CardViewTextItemComponent] + imports: [NoopTranslateModule, NoopAnimationsModule, CardViewTextItemComponent] }); fixture = TestBed.createComponent(CardViewTextItemComponent); component = fixture.componentInstance; diff --git a/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.ts b/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.ts index 75eab8962c..b38d53d67a 100644 --- a/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.ts +++ b/lib/core/src/lib/card-view/components/card-view-textitem/card-view-textitem.component.ts @@ -30,6 +30,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { MatInputModule } from '@angular/material/input'; import { MatIconModule } from '@angular/material/icon'; import { MatButtonModule } from '@angular/material/button'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; export const DEFAULT_SEPARATOR = ', '; const templateTypes = { @@ -52,7 +53,8 @@ const templateTypes = { MatChipsModule, MatIconModule, FormsModule, - MatButtonModule + MatButtonModule, + MatSnackBarModule ], templateUrl: './card-view-textitem.component.html', styleUrls: ['./card-view-textitem.component.scss'], diff --git a/lib/core/src/lib/card-view/components/card-view/card-view.component.spec.ts b/lib/core/src/lib/card-view/components/card-view/card-view.component.spec.ts index f63ad48219..0e4946a84d 100644 --- a/lib/core/src/lib/card-view/components/card-view/card-view.component.spec.ts +++ b/lib/core/src/lib/card-view/components/card-view/card-view.component.spec.ts @@ -28,9 +28,10 @@ import { CardViewItemDispatcherComponent } from '../card-view-item-dispatcher/ca import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatSelectHarness } from '@angular/material/select/testing'; -import { MatSnackBarModule } from '@angular/material/snack-bar'; import { MatDialogModule } from '@angular/material/dialog'; -import { CoreTestingModule } from '@alfresco/adf-core'; +import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { MatSnackBarModule } from '@angular/material/snack-bar'; describe('CardViewComponent', () => { let loader: HarnessLoader; @@ -39,7 +40,7 @@ describe('CardViewComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, MatSnackBarModule, MatDialogModule, CardViewComponent] + imports: [NoopTranslateModule, NoopAnimationsModule, MatSnackBarModule, MatDialogModule, CardViewComponent] }); fixture = TestBed.createComponent(CardViewComponent); diff --git a/lib/core/src/lib/comments/comments.component.ts b/lib/core/src/lib/comments/comments.component.ts index e7ccaf2c77..3c1791fb10 100644 --- a/lib/core/src/lib/comments/comments.component.ts +++ b/lib/core/src/lib/comments/comments.component.ts @@ -73,8 +73,8 @@ export class CommentsComponent implements OnChanges { return; } - this.commentsService.get(this.id).subscribe( - (comments: CommentModel[]) => { + this.commentsService.get(this.id).subscribe({ + next: (comments) => { if (!this.isArrayInstance(comments)) { return; } @@ -82,10 +82,10 @@ export class CommentsComponent implements OnChanges { comments = this.sortedComments(comments); this.comments.push(...comments); }, - (err) => { + error: (err) => { this.error.emit(err); } - ); + }); } addComment() { @@ -95,18 +95,18 @@ export class CommentsComponent implements OnChanges { this.beingAdded = true; - this.commentsService.add(this.id, this.message).subscribe( - (res: CommentModel) => { + this.commentsService.add(this.id, this.message).subscribe({ + next: (res) => { this.addToComments(res); this.resetMessage(); }, - (err) => { + error: (err) => { this.error.emit(err); }, - () => { + complete: () => { this.beingAdded = false; } - ); + }); } clearMessage(event: Event): void { @@ -135,7 +135,7 @@ export class CommentsComponent implements OnChanges { } private sortedComments(comments: CommentModel[]): CommentModel[] { - return comments.sort((comment1: CommentModel, comment2: CommentModel) => { + return comments.sort((comment1, comment2) => { const date1 = new Date(comment1.created); const date2 = new Date(comment2.created); diff --git a/lib/core/src/lib/common/mock/app-config.service.mock.ts b/lib/core/src/lib/common/mock/app-config.service.mock.ts index eff13e1376..de78366536 100644 --- a/lib/core/src/lib/common/mock/app-config.service.mock.ts +++ b/lib/core/src/lib/common/mock/app-config.service.mock.ts @@ -17,24 +17,21 @@ import { Injectable } from '@angular/core'; import { AppConfigService, Status } from '../../app-config/app-config.service'; -import { HttpClient } from '@angular/common/http'; -import { ExtensionService } from '@alfresco/adf-extensions'; @Injectable() export class AppConfigServiceMock extends AppConfigService { + constructor() { + super(); - config: any = { - application: { - name: 'Alfresco ADF Application', - storagePrefix: 'ADF_APP' - }, - ecmHost: 'http://{hostname}{:port}/ecm', - bpmHost: 'http://{hostname}{:port}/bpm', - logLevel: 'silent' - }; - - constructor(http: HttpClient, extensionService: ExtensionService) { - super(http, extensionService); + this.config = { + application: { + name: 'Alfresco ADF Application', + storagePrefix: 'ADF_APP' + }, + ecmHost: 'http://{hostname}{:port}/ecm', + bpmHost: 'http://{hostname}{:port}/bpm', + logLevel: 'silent' + }; } load(callback?: (...args: any[]) => any): Promise { diff --git a/lib/core/src/lib/common/services/directionality-config-factory.ts b/lib/core/src/lib/common/services/directionality-config-factory.ts deleted file mode 100644 index 94f3a1622c..0000000000 --- a/lib/core/src/lib/common/services/directionality-config-factory.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*! - * @license - * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { DirectionalityConfigService } from './directionality-config.service'; - -// eslint-disable-next-line prefer-arrow/prefer-arrow-functions -/** - * Creates a factory for Angular modules - * - * @param directionalityConfigService service dependency - * @returns a factory function - */ -export function directionalityConfigFactory(directionalityConfigService: DirectionalityConfigService) { - return () => directionalityConfigService; -} diff --git a/lib/core/src/lib/common/services/directionality-config.service.spec.ts b/lib/core/src/lib/common/services/directionality-config.service.spec.ts deleted file mode 100644 index 30966dd424..0000000000 --- a/lib/core/src/lib/common/services/directionality-config.service.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -/*! - * @license - * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { TestBed } from '@angular/core/testing'; -import { UserPreferencesService } from './user-preferences.service'; -import { DirectionalityConfigService } from './directionality-config.service'; -import { directionalityConfigFactory } from './directionality-config-factory'; -import { APP_INITIALIZER } from '@angular/core'; -import { NoopTranslateModule } from '@alfresco/adf-core'; - -describe('DirectionalityConfigService', () => { - let userPreferencesService: UserPreferencesService; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [NoopTranslateModule], - providers: [ - UserPreferencesService, - { - provide: APP_INITIALIZER, - useFactory: directionalityConfigFactory, - deps: [DirectionalityConfigService], - multi: true - } - ] - }); - userPreferencesService = TestBed.inject(UserPreferencesService); - }); - - it('should set document direction on textOrientation event to `rtl`', () => { - userPreferencesService.set('textOrientation', 'rtl'); - expect(document.body.getAttribute('dir')).toBe('rtl'); - }); - - it('should set document direction on textOrientation event to `ltr`', () => { - userPreferencesService.set('textOrientation', 'ltr'); - expect(document.body.getAttribute('dir')).toBe('ltr'); - }); -}); diff --git a/lib/core/src/lib/common/services/directionality-config.service.ts b/lib/core/src/lib/common/services/directionality-config.service.ts deleted file mode 100644 index f54b136311..0000000000 --- a/lib/core/src/lib/common/services/directionality-config.service.ts +++ /dev/null @@ -1,42 +0,0 @@ -/*! - * @license - * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Injectable, Inject, Renderer2, RendererFactory2 } from '@angular/core'; -import { Directionality, Direction } from '@angular/cdk/bidi'; -import { UserPreferencesService } from './user-preferences.service'; -import { DOCUMENT } from '@angular/common'; - -@Injectable({ - providedIn: 'root' -}) -export class DirectionalityConfigService { - constructor( - @Inject(DOCUMENT) private document: any, - private rendererFactory: RendererFactory2, - private userPreferencesService: UserPreferencesService, - private directionality: Directionality - ) { - const renderer: Renderer2 = this.rendererFactory.createRenderer(null, null); - - this.userPreferencesService - .select('textOrientation') - .subscribe((direction: Direction) => { - renderer.setAttribute(this.document.body, 'dir', direction); - (this.directionality as any).value = direction; - }); - } -} diff --git a/lib/core/src/lib/common/services/storage.service.spec.ts b/lib/core/src/lib/common/services/storage.service.spec.ts index 1696402743..7873340277 100644 --- a/lib/core/src/lib/common/services/storage.service.spec.ts +++ b/lib/core/src/lib/common/services/storage.service.spec.ts @@ -18,9 +18,7 @@ import { TestBed } from '@angular/core/testing'; import { AppConfigService } from '../../app-config/app-config.service'; import { StorageService } from '../../common/services/storage.service'; -import { CoreTestingModule } from '../../testing'; -import { RedirectAuthService } from '../../auth'; -import { EMPTY } from 'rxjs'; +import { NoopAuthModule, NoopTranslateModule } from '@alfresco/adf-core'; describe('StorageService', () => { let storage: StorageService; @@ -31,48 +29,41 @@ describe('StorageService', () => { describe('with prefix', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - providers: [{ provide: RedirectAuthService, useValue: { onLogin: EMPTY, init: () => [] } }] + imports: [NoopTranslateModule, NoopAuthModule] }); appConfig = TestBed.inject(AppConfigService); storage = TestBed.inject(StorageService); }); - it('should get the prefix for the storage from app config', (done) => { - appConfig.load().then(() => { - expect(storage.prefix).toBe('ADF_APP_'); - done(); - }); + it('should get the prefix for the storage from app config', async () => { + await appConfig.load(); + expect(storage.prefix).toBe('ADF_APP_'); }); - it('should set a property with the prefix in the local storage', (done) => { - appConfig.load().then(() => { - storage.clear(); - storage.setItem(key, value); - const storageKey = localStorage.key(0); - expect(storageKey).toBe('ADF_APP_' + key); - expect(localStorage.getItem(storageKey)).toBe(value); - done(); - }); + it('should set a property with the prefix in the local storage', async () => { + await appConfig.load(); + + storage.clear(); + storage.setItem(key, value); + const storageKey = localStorage.key(0); + expect(storageKey).toBe('ADF_APP_' + key); + expect(localStorage.getItem(storageKey)).toBe(value); }); - it('should be able to get a property from the local storage', (done) => { + it('should be able to get a property from the local storage', async () => { storage.clear(); - appConfig.load().then(() => { - storage.setItem(key, value); + await appConfig.load(); + storage.setItem(key, value); - expect(storage.getItem(key)).toBe(value); - done(); - }); + expect(storage.getItem(key)).toBe(value); }); }); describe('without prefix', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - providers: [{ provide: RedirectAuthService, useValue: { onLogin: EMPTY, init: () => [] } }] + imports: [NoopAuthModule] }); appConfig = TestBed.inject(AppConfigService); @@ -84,20 +75,16 @@ describe('StorageService', () => { storage = TestBed.inject(StorageService); }); - it('should set an empty prefix when the it is not defined in the app config', (done) => { - appConfig.load().then(() => { - expect(storage.prefix).toBe(''); - done(); - }); + it('should set an empty prefix when the it is not defined in the app config', async () => { + await appConfig.load(); + expect(storage.prefix).toBe(''); }); - it('should set a property without a prefix in the local storage', (done) => { - appConfig.load().then(() => { - storage.setItem(key, value); + it('should set a property without a prefix in the local storage', async () => { + await appConfig.load(); + storage.setItem(key, value); - expect(localStorage.getItem(key)).toBe(value); - done(); - }); + expect(localStorage.getItem(key)).toBe(value); }); }); }); diff --git a/lib/core/src/lib/common/services/user-preferences.service.spec.ts b/lib/core/src/lib/common/services/user-preferences.service.spec.ts index a9685af9c8..4e16acac58 100644 --- a/lib/core/src/lib/common/services/user-preferences.service.spec.ts +++ b/lib/core/src/lib/common/services/user-preferences.service.spec.ts @@ -33,9 +33,7 @@ describe('UserPreferencesService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [NoopTranslateModule], - providers: [ - { provide: AppConfigService, useClass: AppConfigServiceMock } - ] + providers: [{ provide: AppConfigService, useClass: AppConfigServiceMock }] }); appConfig = TestBed.inject(AppConfigService); appConfig.config = { @@ -56,6 +54,16 @@ describe('UserPreferencesService', () => { TestBed.resetTestingModule(); }); + it('should set document direction on textOrientation event to `rtl`', () => { + preferences.set('textOrientation', 'rtl'); + expect(document.body.getAttribute('dir')).toBe('rtl'); + }); + + it('should set document direction on textOrientation event to `ltr`', () => { + preferences.set('textOrientation', 'ltr'); + expect(document.body.getAttribute('dir')).toBe('ltr'); + }); + describe(' with pagination config', () => { it('should get default pagination from app config', (done) => { appConfig.config.pagination.size = 0; diff --git a/lib/core/src/lib/common/services/user-preferences.service.ts b/lib/core/src/lib/common/services/user-preferences.service.ts index b2bb5ccf5b..95e63f1f9e 100644 --- a/lib/core/src/lib/common/services/user-preferences.service.ts +++ b/lib/core/src/lib/common/services/user-preferences.service.ts @@ -15,13 +15,15 @@ * limitations under the License. */ -import { Injectable } from '@angular/core'; +import { inject, Injectable, RendererFactory2 } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { Observable, BehaviorSubject } from 'rxjs'; import { AppConfigService, AppConfigValues } from '../../app-config/app-config.service'; import { StorageService } from './storage.service'; import { distinctUntilChanged, map } from 'rxjs/operators'; import { LanguageItem } from './language-item.interface'; +import { DOCUMENT } from '@angular/common'; +import { Directionality, Direction } from '@angular/cdk/bidi'; // eslint-disable-next-line no-shadow export enum UserPreferenceValues { @@ -35,6 +37,9 @@ export enum UserPreferenceValues { providedIn: 'root' }) export class UserPreferencesService { + private document = inject(DOCUMENT); + private rendererFactory = inject(RendererFactory2); + private directionality = inject(Directionality); defaults = { paginationSize: 25, @@ -47,17 +52,20 @@ export class UserPreferencesService { private onChangeSubject: BehaviorSubject; onChange: Observable; - constructor( - public translate: TranslateService, - private appConfig: AppConfigService, - private storage: StorageService - ) { + constructor(public translate: TranslateService, private appConfig: AppConfigService, private storage: StorageService) { this.onChangeSubject = new BehaviorSubject(this.userPreferenceStatus); this.onChange = this.onChangeSubject.asObservable(); this.appConfig.onLoad.subscribe(() => { this.initUserPreferenceStatus(); }); + + const renderer = this.rendererFactory.createRenderer(null, null); + + this.select('textOrientation').subscribe((direction: Direction) => { + renderer.setAttribute(this.document.body, 'dir', direction); + (this.directionality as any).value = direction; + }); } private initUserPreferenceStatus() { @@ -87,11 +95,10 @@ export class UserPreferencesService { * @returns Notification callback */ select(property: string): Observable { - return this.onChange - .pipe( - map((userPreferenceStatus) => userPreferenceStatus[property]), - distinctUntilChanged() - ); + return this.onChange.pipe( + map((userPreferenceStatus) => userPreferenceStatus[property]), + distinctUntilChanged() + ); } /** @@ -120,10 +127,7 @@ export class UserPreferencesService { if (!property) { return; } - this.storage.setItem( - this.getPropertyKey(property), - value - ); + this.storage.setItem(this.getPropertyKey(property), value); this.userPreferenceStatus[property] = value; this.onChangeSubject.next(this.userPreferenceStatus); } @@ -152,9 +156,7 @@ export class UserPreferencesService { if (!property) { return false; } - return this.storage.hasItem( - this.getPropertyKey(property) - ); + return this.storage.hasItem(this.getPropertyKey(property)); } /** @@ -243,10 +245,12 @@ export class UserPreferencesService { } private getLanguageByKey(key: string): LanguageItem { - return ( - this.appConfig - .get>(AppConfigValues.APP_CONFIG_LANGUAGES_KEY, [{ key: 'en' } as LanguageItem]) - .find((language) => key.includes(language.key)) || { key: 'en' } as LanguageItem - ); + const defaultLanguage = { key: 'en' } as LanguageItem; + + const registeredLanguages = this.appConfig.get>(AppConfigValues.APP_CONFIG_LANGUAGES_KEY); + if (registeredLanguages && Array.isArray(registeredLanguages)) { + return registeredLanguages.find((language) => key.includes(language.key)) || defaultLanguage; + } + return defaultLanguage; } } diff --git a/lib/core/src/lib/context-menu/context-menu-overlay.service.spec.ts b/lib/core/src/lib/context-menu/context-menu-overlay.service.spec.ts index 5037c8e4c5..01379023b8 100644 --- a/lib/core/src/lib/context-menu/context-menu-overlay.service.spec.ts +++ b/lib/core/src/lib/context-menu/context-menu-overlay.service.spec.ts @@ -16,7 +16,6 @@ */ import { Overlay } from '@angular/cdk/overlay'; -import { CoreTestingModule } from '../testing/core.testing.module'; import { ContextMenuOverlayService } from './context-menu-overlay.service'; import { Injector } from '@angular/core'; import { TestBed } from '@angular/core/testing'; @@ -35,7 +34,6 @@ describe('ContextMenuOverlayService', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], providers: [Overlay] }); overlay = TestBed.inject(Overlay); diff --git a/lib/core/src/lib/core.module.ts b/lib/core/src/lib/core.module.ts index eb417561a3..fcc5acac55 100644 --- a/lib/core/src/lib/core.module.ts +++ b/lib/core/src/lib/core.module.ts @@ -39,8 +39,6 @@ import { CORE_DIRECTIVES } from './directives/directive.module'; import { CORE_PIPES } from './pipes/pipe.module'; import { TranslationService } from './translation/translation.service'; import { TranslateLoaderService } from './translation/translate-loader.service'; -import { directionalityConfigFactory } from './common/services/directionality-config-factory'; -import { DirectionalityConfigService } from './common/services/directionality-config.service'; import { SEARCH_TEXT_INPUT_DIRECTIVES } from './search-text/search-text-input.module'; import { AdfHttpClient } from '@alfresco/adf-core/api'; import { AuthenticationInterceptor, Authentication } from '@alfresco/adf-core/auth'; @@ -145,12 +143,6 @@ export class CoreModule { deps: [AppConfigService, StorageService, AdfHttpClient, StoragePrefixFactory], multi: true }, - { - provide: APP_INITIALIZER, - useFactory: directionalityConfigFactory, - deps: [DirectionalityConfigService], - multi: true - }, { provide: HTTP_INTERCEPTORS, useClass: AuthenticationInterceptor, multi: true }, { provide: Authentication, useClass: AuthenticationService }, { diff --git a/lib/core/src/lib/datatable/components/columns-selector/columns-selector.component.spec.ts b/lib/core/src/lib/datatable/components/columns-selector/columns-selector.component.spec.ts index c893192a54..63ddfd5a4c 100644 --- a/lib/core/src/lib/datatable/components/columns-selector/columns-selector.component.spec.ts +++ b/lib/core/src/lib/datatable/components/columns-selector/columns-selector.component.spec.ts @@ -20,11 +20,11 @@ import { ColumnsSelectorComponent } from './columns-selector.component'; import { DataColumn } from '../../data/data-column.model'; import { Observable, Subject } from 'rxjs'; import { MatMenuTrigger } from '@angular/material/menu'; -import { CoreTestingModule } from '../../../testing'; import { By } from '@angular/platform-browser'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { HarnessLoader } from '@angular/cdk/testing'; import { MatCheckboxHarness } from '@angular/material/checkbox/testing'; +import { NoopTranslateModule } from '@alfresco/adf-core'; describe('ColumnsSelectorComponent', () => { let fixture: ComponentFixture; @@ -40,8 +40,8 @@ describe('ColumnsSelectorComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, ColumnsSelectorComponent] - }).compileComponents(); + imports: [NoopTranslateModule, ColumnsSelectorComponent] + }); fixture = TestBed.createComponent(ColumnsSelectorComponent); loader = TestbedHarnessEnvironment.loader(fixture); diff --git a/lib/core/src/lib/datatable/components/empty-list/empty-list.component.spec.ts b/lib/core/src/lib/datatable/components/empty-list/empty-list.component.spec.ts index 4c1151c1fd..68d28e003a 100644 --- a/lib/core/src/lib/datatable/components/empty-list/empty-list.component.spec.ts +++ b/lib/core/src/lib/datatable/components/empty-list/empty-list.component.spec.ts @@ -17,14 +17,13 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { EmptyListComponent } from './empty-list.component'; -import { CoreTestingModule } from '../../../testing/core.testing.module'; describe('EmptyListComponentComponent', () => { let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule] + imports: [EmptyListComponent] }); fixture = TestBed.createComponent(EmptyListComponent); }); diff --git a/lib/core/src/lib/datatable/components/json-cell/json-cell.component.spec.ts b/lib/core/src/lib/datatable/components/json-cell/json-cell.component.spec.ts index 1c22f55c63..5cd793b412 100644 --- a/lib/core/src/lib/datatable/components/json-cell/json-cell.component.spec.ts +++ b/lib/core/src/lib/datatable/components/json-cell/json-cell.component.spec.ts @@ -18,7 +18,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { ObjectDataColumn } from '../../data/object-datacolumn.model'; -import { CoreTestingModule } from '../../../testing/core.testing.module'; import { JsonCellComponent } from './json-cell.component'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { HarnessLoader } from '@angular/cdk/testing'; @@ -34,7 +33,7 @@ describe('JsonCellComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule] + imports: [JsonCellComponent] }); fixture = TestBed.createComponent(JsonCellComponent); component = fixture.componentInstance; diff --git a/lib/core/src/lib/datatable/components/json-cell/json-cell.component.ts b/lib/core/src/lib/datatable/components/json-cell/json-cell.component.ts index a9c4832bdb..02ad2be886 100644 --- a/lib/core/src/lib/datatable/components/json-cell/json-cell.component.ts +++ b/lib/core/src/lib/datatable/components/json-cell/json-cell.component.ts @@ -17,7 +17,7 @@ import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation, Input } from '@angular/core'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; -import { MatDialog } from '@angular/material/dialog'; +import { MatDialog, MatDialogModule } from '@angular/material/dialog'; import { EditJsonDialogComponent, EditJsonDialogSettings } from '../../../dialogs/edit-json/edit-json.dialog'; import { CommonModule } from '@angular/common'; import { MatButtonModule } from '@angular/material/button'; @@ -25,7 +25,7 @@ import { MatButtonModule } from '@angular/material/button'; @Component({ selector: 'adf-json-cell', standalone: true, - imports: [CommonModule, MatButtonModule], + imports: [CommonModule, MatButtonModule, MatDialogModule], changeDetection: ChangeDetectionStrategy.OnPush, template: ` diff --git a/lib/core/src/lib/datatable/components/location-cell/location-cell.component.spec.ts b/lib/core/src/lib/datatable/components/location-cell/location-cell.component.spec.ts index c7250d6ee1..337f96b228 100644 --- a/lib/core/src/lib/datatable/components/location-cell/location-cell.component.spec.ts +++ b/lib/core/src/lib/datatable/components/location-cell/location-cell.component.spec.ts @@ -19,7 +19,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter'; import { ObjectDataColumn } from '../../data/object-datacolumn.model'; import { LocationCellComponent } from './location-cell.component'; -import { CoreTestingModule } from '../../../testing/core.testing.module'; +import { RouterTestingModule } from '@angular/router/testing'; describe('LocationCellComponent', () => { let component: LocationCellComponent; @@ -30,10 +30,7 @@ describe('LocationCellComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [ - LocationCellComponent, - CoreTestingModule - ] + imports: [RouterTestingModule, LocationCellComponent] }); fixture = TestBed.createComponent(LocationCellComponent); component = fixture.componentInstance; @@ -52,12 +49,9 @@ describe('LocationCellComponent', () => { } }; - columnData = { format: '/files', type: 'location', key: 'path'}; + columnData = { format: '/files', type: 'location', key: 'path' }; - dataTableAdapter = new ObjectDataTableAdapter( - [rowData], - [ new ObjectDataColumn(columnData) ] - ); + dataTableAdapter = new ObjectDataTableAdapter([rowData], [new ObjectDataColumn(columnData)]); component.link = []; component.column = dataTableAdapter.getColumns()[0]; @@ -78,7 +72,7 @@ describe('LocationCellComponent', () => { it('should set router link', () => { fixture.detectChanges(); - expect(component.link).toEqual([ columnData.format , rowData.path.elements[2].id ]); + expect(component.link).toEqual([columnData.format, rowData.path.elements[2].id]); }); it('should NOT set router link when format NOT provided', () => { @@ -99,7 +93,7 @@ describe('LocationCellComponent', () => { expect(value).toBe(''); done(); }); - }); + }); it('should not setup cell when path is missing required properties', (done) => { rowData.path = { someProp: '' }; diff --git a/lib/core/src/lib/datatable/data-column/data-column.component.spec.ts b/lib/core/src/lib/datatable/data-column/data-column.component.spec.ts index 8b3b291c3e..4a9f159042 100644 --- a/lib/core/src/lib/datatable/data-column/data-column.component.spec.ts +++ b/lib/core/src/lib/datatable/data-column/data-column.component.spec.ts @@ -16,16 +16,8 @@ */ import { DataColumnComponent } from './data-column.component'; -import { CoreTestingModule } from '../../testing/core.testing.module'; -import { TestBed } from '@angular/core/testing'; describe('DataColumnListComponent', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [CoreTestingModule] - }); - }); - it('should setup screen reader title for thumbnails', () => { const component = new DataColumnComponent(); component.key = '$thumbnail'; diff --git a/lib/core/src/lib/datatable/directives/loading-template.directive.spec.ts b/lib/core/src/lib/datatable/directives/loading-template.directive.spec.ts index efc18441a9..ff308c8bab 100644 --- a/lib/core/src/lib/datatable/directives/loading-template.directive.spec.ts +++ b/lib/core/src/lib/datatable/directives/loading-template.directive.spec.ts @@ -18,7 +18,6 @@ import { TestBed, ComponentFixture } from '@angular/core/testing'; import { DataTableComponent } from '../components/datatable/datatable.component'; import { LoadingContentTemplateDirective } from './loading-template.directive'; -import { CoreTestingModule } from '../../testing/core.testing.module'; describe('LoadingContentTemplateDirective', () => { let fixture: ComponentFixture; @@ -27,7 +26,7 @@ describe('LoadingContentTemplateDirective', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule] + imports: [DataTableComponent] }); fixture = TestBed.createComponent(DataTableComponent); dataTable = fixture.componentInstance; diff --git a/lib/core/src/lib/datatable/directives/no-content-template.directive.spec.ts b/lib/core/src/lib/datatable/directives/no-content-template.directive.spec.ts index 5f1670f090..7cd1b15362 100644 --- a/lib/core/src/lib/datatable/directives/no-content-template.directive.spec.ts +++ b/lib/core/src/lib/datatable/directives/no-content-template.directive.spec.ts @@ -18,7 +18,6 @@ import { TestBed, ComponentFixture } from '@angular/core/testing'; import { DataTableComponent } from '../components/datatable/datatable.component'; import { NoContentTemplateDirective } from './no-content-template.directive'; -import { CoreTestingModule } from '../../testing/core.testing.module'; describe('NoContentTemplateDirective', () => { let fixture: ComponentFixture; @@ -27,7 +26,7 @@ describe('NoContentTemplateDirective', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule] + imports: [DataTableComponent] }); fixture = TestBed.createComponent(DataTableComponent); dataTable = fixture.componentInstance; diff --git a/lib/core/src/lib/dialogs/unsaved-changes-dialog/unsaved-changes.guard.spec.ts b/lib/core/src/lib/dialogs/unsaved-changes-dialog/unsaved-changes.guard.spec.ts index 3156068aeb..d72d763f8e 100644 --- a/lib/core/src/lib/dialogs/unsaved-changes-dialog/unsaved-changes.guard.spec.ts +++ b/lib/core/src/lib/dialogs/unsaved-changes-dialog/unsaved-changes.guard.spec.ts @@ -16,16 +16,17 @@ */ import { TestBed } from '@angular/core/testing'; -import { CoreTestingModule, UnsavedChangesDialogComponent, UnsavedChangesGuard } from '@alfresco/adf-core'; -import { MatDialog, MatDialogRef } from '@angular/material/dialog'; +import { MatDialog, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { Observable, Subject } from 'rxjs'; +import { UnsavedChangesDialogComponent } from './unsaved-changes-dialog.component'; +import { UnsavedChangesGuard } from './unsaved-changes.guard'; describe('UnsavedChangesGuard', () => { let guard: UnsavedChangesGuard; beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule] + imports: [MatDialogModule] }); guard = TestBed.inject(UnsavedChangesGuard); }); diff --git a/lib/core/src/lib/directives/highlight.directive.spec.ts b/lib/core/src/lib/directives/highlight.directive.spec.ts index 40d10280bb..cbab5ded0c 100644 --- a/lib/core/src/lib/directives/highlight.directive.spec.ts +++ b/lib/core/src/lib/directives/highlight.directive.spec.ts @@ -20,21 +20,22 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { HighlightTransformService } from '../common/services/highlight-transform.service'; import { HighlightDirective } from './highlight.directive'; -import { CoreTestingModule } from '../testing/core.testing.module'; /* spellchecker: disable */ -const template: string = ` -
-
Lorem ipsum salana-eyong-aysis dolor sit amet
-
Lorem ipsum salana-eyong-aysis dolor sit amet
-
consectetur adipiscing elit
-
sed do eiusmod salana-eyong-aysis tempor incididunt
-
-
-
Lorem ipsum salana-eyong-aysis dolor sit amet
-
`; - -@Component({ selector: 'adf-test-component', template }) +@Component({ + selector: 'adf-test-component', + standalone: true, + imports: [HighlightDirective], + template: `
+
Lorem ipsum salana-eyong-aysis dolor sit amet
+
Lorem ipsum salana-eyong-aysis dolor sit amet
+
consectetur adipiscing elit
+
sed do eiusmod salana-eyong-aysis tempor incididunt
+
+
+
Lorem ipsum salana-eyong-aysis dolor sit amet
+
` +}) class TestComponent { @ViewChildren(HighlightDirective) public highlightDirectives; } @@ -45,8 +46,7 @@ describe('HighlightDirective', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - declarations: [TestComponent] + imports: [TestComponent] }); fixture = TestBed.createComponent(TestComponent); component = fixture.componentInstance; diff --git a/lib/core/src/lib/directives/logout.directive.spec.ts b/lib/core/src/lib/directives/logout.directive.spec.ts index d078929caa..67cb238384 100644 --- a/lib/core/src/lib/directives/logout.directive.spec.ts +++ b/lib/core/src/lib/directives/logout.directive.spec.ts @@ -22,12 +22,14 @@ import { of, throwError } from 'rxjs'; import { AuthenticationService } from '../auth/services/authentication.service'; import { AppConfigService } from '../app-config/app-config.service'; import { LogoutDirective } from './logout.directive'; -import { CoreTestingModule } from '../testing/core.testing.module'; +import { NoopAuthModule } from '@alfresco/adf-core'; describe('LogoutDirective', () => { describe('No input', () => { @Component({ selector: 'adf-test-component', + standalone: true, + imports: [LogoutDirective], template: '' }) class TestComponent { @@ -42,8 +44,7 @@ describe('LogoutDirective', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - declarations: [TestComponent] + imports: [NoopAuthModule, TestComponent] }); router = TestBed.inject(Router); authService = TestBed.inject(AuthenticationService); @@ -104,6 +105,8 @@ describe('LogoutDirective', () => { describe('redirectUri', () => { @Component({ selector: 'adf-test-component', + standalone: true, + imports: [LogoutDirective], template: '' }) class TestComponent { @@ -117,8 +120,7 @@ describe('LogoutDirective', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - declarations: [TestComponent] + imports: [NoopAuthModule, TestComponent] }); router = TestBed.inject(Router); authService = TestBed.inject(AuthenticationService); @@ -141,6 +143,8 @@ describe('LogoutDirective', () => { describe('enableRedirect', () => { @Component({ selector: 'adf-test-component', + standalone: true, + imports: [LogoutDirective], template: '' }) class TestComponent { @@ -154,8 +158,7 @@ describe('LogoutDirective', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - declarations: [TestComponent] + imports: [NoopAuthModule, TestComponent] }); router = TestBed.inject(Router); authService = TestBed.inject(AuthenticationService); diff --git a/lib/core/src/lib/info-drawer/info-drawer.component.spec.ts b/lib/core/src/lib/info-drawer/info-drawer.component.spec.ts index 909924ec3f..fd3fff1b6b 100644 --- a/lib/core/src/lib/info-drawer/info-drawer.component.spec.ts +++ b/lib/core/src/lib/info-drawer/info-drawer.component.spec.ts @@ -19,27 +19,23 @@ import { Component } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatTabChangeEvent } from '@angular/material/tabs'; import { By } from '@angular/platform-browser'; -import { InfoDrawerComponent } from './info-drawer.component'; -import { of } from 'rxjs'; -import { TranslateService } from '@ngx-translate/core'; -import { CoreTestingModule } from '../testing/core.testing.module'; +import { InfoDrawerComponent, InfoDrawerTabComponent } from './info-drawer.component'; import { ESCAPE } from '@angular/cdk/keycodes'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatTabGroupHarness } from '@angular/material/tabs/testing'; +import { NoopTranslateModule } from '@alfresco/adf-core'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('InfoDrawerComponent', () => { let element: HTMLElement; let component: InfoDrawerComponent; - let translateService: TranslateService; let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule] + imports: [NoopTranslateModule, InfoDrawerComponent] }); - translateService = TestBed.inject(TranslateService); - spyOn(translateService, 'get').and.callFake((key) => of(key)); fixture = TestBed.createComponent(InfoDrawerComponent); element = fixture.nativeElement; @@ -86,6 +82,8 @@ describe('InfoDrawerComponent', () => { }); @Component({ + standalone: true, + imports: [InfoDrawerTabComponent, InfoDrawerComponent], template: ` @@ -102,18 +100,14 @@ class CustomInfoDrawerComponent extends InfoDrawerComponent { describe('Custom InfoDrawer', () => { let fixture: ComponentFixture; let component: CustomInfoDrawerComponent; - let translateService: TranslateService; let loader: HarnessLoader; const getNodeIcon = () => fixture.debugElement.queryAll(By.css('[info-drawer-node-icon]')); beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - declarations: [CustomInfoDrawerComponent] + imports: [NoopAnimationsModule, NoopTranslateModule, CustomInfoDrawerComponent] }); - translateService = TestBed.inject(TranslateService); - spyOn(translateService, 'get').and.callFake((key) => of(key)); fixture = TestBed.createComponent(CustomInfoDrawerComponent); fixture.detectChanges(); @@ -170,6 +164,8 @@ describe('Custom InfoDrawer', () => { }); @Component({ + standalone: true, + imports: [InfoDrawerComponent], template: ` ` }) class VisibilityInfoDrawerComponent extends InfoDrawerComponent { @@ -184,8 +180,7 @@ describe('Header visibility InfoDrawer', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - declarations: [VisibilityInfoDrawerComponent] + imports: [NoopTranslateModule, VisibilityInfoDrawerComponent] }); fixture = TestBed.createComponent(VisibilityInfoDrawerComponent); fixture.detectChanges(); diff --git a/lib/core/src/lib/snackbar-content/snackbar-content.component.spec.ts b/lib/core/src/lib/snackbar-content/snackbar-content.component.spec.ts index 2c2a6b8325..91b553b8d0 100644 --- a/lib/core/src/lib/snackbar-content/snackbar-content.component.spec.ts +++ b/lib/core/src/lib/snackbar-content/snackbar-content.component.spec.ts @@ -16,21 +16,20 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatIcon, MatIconModule } from '@angular/material/icon'; -import { MAT_SNACK_BAR_DATA, MatSnackBarModule, MatSnackBarRef } from '@angular/material/snack-bar'; -import { MatButtonModule } from '@angular/material/button'; +import { MatIcon } from '@angular/material/icon'; +import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar'; import { By } from '@angular/platform-browser'; import { SnackbarContentComponent } from './snackbar-content.component'; -import { CoreTestingModule } from '@alfresco/adf-core'; +import { CoreTestingModule, NoopTranslateModule } from '@alfresco/adf-core'; describe('SnackbarContentComponent', () => { let component: SnackbarContentComponent; let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ + beforeEach(() => { + TestBed.configureTestingModule({ declarations: [SnackbarContentComponent], - imports: [CoreTestingModule, MatIconModule, MatSnackBarModule, MatButtonModule], + imports: [NoopTranslateModule, CoreTestingModule], providers: [ { provide: MatSnackBarRef, @@ -43,7 +42,7 @@ describe('SnackbarContentComponent', () => { useValue: {} } ] - }).compileComponents(); + }); fixture = TestBed.createComponent(SnackbarContentComponent); component = fixture.componentInstance; diff --git a/lib/core/src/lib/templates/empty-content/empty-content.component.spec.ts b/lib/core/src/lib/templates/empty-content/empty-content.component.spec.ts index 71b55caaeb..ba828edc7d 100644 --- a/lib/core/src/lib/templates/empty-content/empty-content.component.spec.ts +++ b/lib/core/src/lib/templates/empty-content/empty-content.component.spec.ts @@ -20,10 +20,13 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; import { of } from 'rxjs'; -import { CoreTestingModule } from '../../testing/core.testing.module'; +import { NoopTranslateModule } from '../../testing/noop-translate.module'; +import { EmptyContentComponent } from './empty-content.component'; @Component({ selector: 'adf-test-component', + standalone: true, + imports: [EmptyContentComponent], template: `
SUBTITLE-1
@@ -40,8 +43,7 @@ describe('EmptyContentComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - declarations: [TestComponent] + imports: [NoopTranslateModule, TestComponent] }); fixture = TestBed.createComponent(TestComponent); translateService = TestBed.inject(TranslateService); @@ -52,8 +54,8 @@ describe('EmptyContentComponent', () => { await fixture.whenStable(); const title = fixture.debugElement.query(By.css('.adf-empty-content__title')); - expect(title).toBeDefined('title element not found'); - expect(title.nativeElement.textContent).toContain('CUSTOM_TITLE', 'incorrect title value'); + expect(title).toBeDefined(); + expect(title.nativeElement.textContent).toContain('CUSTOM_TITLE'); }); it('should translate title and subtitle', async () => { @@ -74,19 +76,19 @@ describe('EmptyContentComponent', () => { const title = fixture.debugElement.query(By.css('.adf-empty-content__title')); const subtitle = fixture.debugElement.query(By.css('.adf-empty-content__subtitle')); - expect(title).toBeDefined('title element not found'); - expect(title.nativeElement.textContent).toContain('ENG_CUSTOM_TITLE', 'incorrect title value'); + expect(title).toBeDefined(); + expect(title.nativeElement.textContent).toContain('ENG_CUSTOM_TITLE'); - expect(subtitle).toBeDefined('subtitle element not found'); - expect(subtitle.nativeElement.textContent).toContain('ENG_CUSTOM_SUBTITLE', 'incorrect subtitle value'); + expect(subtitle).toBeDefined(); + expect(subtitle.nativeElement.textContent).toContain('ENG_CUSTOM_SUBTITLE'); }); it('should render multiple subtitle elements', () => { const subTitles = fixture.debugElement.queryAll(By.css('.adf-empty-content__text')); expect(subTitles.length).toBe(3); - expect(subTitles[0].nativeElement.textContent).toContain('SUBTITLE-1', 'missing SUBTITLE-1'); - expect(subTitles[1].nativeElement.textContent).toContain('SUBTITLE-2', 'missing SUBTITLE-2'); - expect(subTitles[2].nativeElement.textContent).toContain('SUBTITLE-3', 'missing SUBTITLE-3'); + expect(subTitles[0].nativeElement.textContent).toContain('SUBTITLE-1'); + expect(subTitles[1].nativeElement.textContent).toContain('SUBTITLE-2'); + expect(subTitles[2].nativeElement.textContent).toContain('SUBTITLE-3'); }); }); diff --git a/lib/core/src/lib/testing/core.testing.module.ts b/lib/core/src/lib/testing/core.testing.module.ts index 99fca4b510..a885001b76 100644 --- a/lib/core/src/lib/testing/core.testing.module.ts +++ b/lib/core/src/lib/testing/core.testing.module.ts @@ -15,45 +15,13 @@ * limitations under the License. */ -import { NgModule, APP_INITIALIZER } from '@angular/core'; +import { NgModule } from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { RouterTestingModule } from '@angular/router/testing'; import { CoreModule } from '../core.module'; -import { AppConfigService } from '../app-config/app-config.service'; -import { AppConfigServiceMock } from '../common/mock/app-config.service.mock'; -import { DatePipe } from '@angular/common'; -import { CookieService } from '../common/services/cookie.service'; -import { CookieServiceMock } from '../mock/cookie.service.mock'; -import { HttpClientModule } from '@angular/common/http'; -import { directionalityConfigFactory } from '../common/services/directionality-config-factory'; -import { DirectionalityConfigService } from '../common/services/directionality-config.service'; -import { AuthModule, RedirectAuthService } from '../auth'; -import { EMPTY, of } from 'rxjs'; import { NoopTranslateModule } from './noop-translate.module'; -import { UserPreferencesService } from '../common/services/user-preferences.service'; +import { NoopAuthModule } from './noop-auth.module'; @NgModule({ - imports: [ - AuthModule.forRoot({ useHash: true }), - NoopAnimationsModule, - RouterTestingModule, - HttpClientModule, - CoreModule.forRoot(), - NoopTranslateModule - ], - providers: [ - DatePipe, - UserPreferencesService, - { provide: AppConfigService, useClass: AppConfigServiceMock }, - { provide: CookieService, useClass: CookieServiceMock }, - { - provide: APP_INITIALIZER, - useFactory: directionalityConfigFactory, - deps: [DirectionalityConfigService], - multi: true - }, - { provide: RedirectAuthService, useValue: { onLogin: EMPTY, init: () => {}, onTokenReceived: of() } } - ], - exports: [NoopAnimationsModule, CoreModule, RouterTestingModule] + imports: [NoopAnimationsModule, CoreModule.forRoot(), NoopTranslateModule, NoopAuthModule] }) export class CoreTestingModule {} diff --git a/lib/core/src/lib/testing/index.ts b/lib/core/src/lib/testing/index.ts index f572c433aa..f4fccb7c41 100644 --- a/lib/core/src/lib/testing/index.ts +++ b/lib/core/src/lib/testing/index.ts @@ -18,3 +18,4 @@ export * from './core.testing.module'; export * from './core.story.module'; export * from './noop-translate.module'; +export * from './noop-auth.module'; diff --git a/lib/core/src/lib/testing/noop-auth.module.ts b/lib/core/src/lib/testing/noop-auth.module.ts new file mode 100644 index 0000000000..052a5156d7 --- /dev/null +++ b/lib/core/src/lib/testing/noop-auth.module.ts @@ -0,0 +1,53 @@ +/*! + * @license + * Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { APP_INITIALIZER, Injectable, NgModule } from '@angular/core'; +import { AuthModule, RedirectAuthService } from '../auth'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AppConfigService, StoragePrefixFactory } from '../app-config'; +import { AppConfigServiceMock, CookieService, StorageService } from '../common'; +import { CookieServiceMock } from '../mock'; +import { EMPTY, of } from 'rxjs'; +import { loadAppConfig } from '../app-config/app-config.loader'; +import { AdfHttpClient } from '@alfresco/adf-core/api'; + +@Injectable({ providedIn: 'root' }) +export class NoopRedirectAuthService extends RedirectAuthService { + onLogin = EMPTY; + onTokenReceived = of(); + + init(): Promise { + return Promise.resolve(true); + } +} + +@NgModule({ + imports: [AuthModule.forRoot({ useHash: true }), HttpClientTestingModule, RouterTestingModule], + providers: [ + { provide: AppConfigService, useClass: AppConfigServiceMock }, + { provide: CookieService, useClass: CookieServiceMock }, + { provide: RedirectAuthService, useClass: NoopRedirectAuthService }, + { + provide: APP_INITIALIZER, + useFactory: loadAppConfig, + deps: [AppConfigService, StorageService, AdfHttpClient, StoragePrefixFactory], + multi: true + } + ] +}) +export class NoopAuthModule {} diff --git a/lib/core/src/lib/testing/noop-translate.module.ts b/lib/core/src/lib/testing/noop-translate.module.ts index 5cff39e450..93302e4a2d 100644 --- a/lib/core/src/lib/testing/noop-translate.module.ts +++ b/lib/core/src/lib/testing/noop-translate.module.ts @@ -15,13 +15,14 @@ * limitations under the License. */ -import { EventEmitter, NgModule } from '@angular/core'; +import { EventEmitter, Injectable, NgModule } from '@angular/core'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { TranslateModule } from '@ngx-translate/core'; import { TranslationService } from '../translation/translation.service'; import { LangChangeEvent } from '../mock'; import { Observable, of } from 'rxjs'; +@Injectable({ providedIn: 'root' }) export class NoopTranslationService implements TranslationService { defaultLang: string = 'en'; userLang: string; diff --git a/lib/core/src/lib/toolbar/toolbar.component.spec.ts b/lib/core/src/lib/toolbar/toolbar.component.spec.ts index 5f4a5d1305..fe1f278dab 100644 --- a/lib/core/src/lib/toolbar/toolbar.component.spec.ts +++ b/lib/core/src/lib/toolbar/toolbar.component.spec.ts @@ -16,16 +16,15 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { CoreTestingModule } from '../testing/core.testing.module'; import { ToolbarComponent } from './toolbar.component'; -import { TOOLBAR_DIRECTIVES } from './toolbar.module'; +import { NoopTranslateModule } from '@alfresco/adf-core'; describe('ToolbarComponent', () => { let fixture: ComponentFixture; beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, ...TOOLBAR_DIRECTIVES] + imports: [NoopTranslateModule, ToolbarComponent] }); fixture = TestBed.createComponent(ToolbarComponent); diff --git a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-more-actions.component.mock.ts b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-more-actions.component.mock.ts index a311f3db58..0b29c34c09 100644 --- a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-more-actions.component.mock.ts +++ b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-more-actions.component.mock.ts @@ -19,11 +19,12 @@ import { Component } from '@angular/core'; import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; import { ViewerComponent } from '../viewer.component'; +import { ViewerMoreActionsComponent } from '../viewer-more-actions.component'; @Component({ selector: 'adf-viewer-container-more-actions', standalone: true, - imports: [ViewerComponent, MatIconModule, MatMenuModule], + imports: [ViewerComponent, MatIconModule, MatMenuModule, ViewerMoreActionsComponent], template: ` @@ -31,7 +32,7 @@ import { ViewerComponent } from '../viewer.component'; dialpad Action One - diff --git a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-open-with.component.mock.ts b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-open-with.component.mock.ts index 5faa2c6acb..0b366fdf1f 100644 --- a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-open-with.component.mock.ts +++ b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-open-with.component.mock.ts @@ -19,11 +19,12 @@ import { Component } from '@angular/core'; import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; import { ViewerComponent } from '../viewer.component'; +import { ViewerOpenWithComponent } from '../viewer-open-with.component'; @Component({ selector: 'adf-viewer-container-open-with', standalone: true, - imports: [ViewerComponent, MatIconModule, MatMenuModule], + imports: [ViewerComponent, MatIconModule, MatMenuModule, ViewerOpenWithComponent], template: ` @@ -31,7 +32,7 @@ import { ViewerComponent } from '../viewer.component'; dialpad Option 1 - diff --git a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-sidebar.component.mock.ts b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-sidebar.component.mock.ts index c7feeb0a2d..e1f90abec6 100644 --- a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-sidebar.component.mock.ts +++ b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-sidebar.component.mock.ts @@ -17,11 +17,12 @@ import { Component } from '@angular/core'; import { ViewerComponent } from '../viewer.component'; +import { ViewerSidebarComponent } from '../viewer-sidebar.component'; @Component({ selector: 'adf-viewer-container-sidebar', standalone: true, - imports: [ViewerComponent], + imports: [ViewerComponent, ViewerSidebarComponent], template: ` diff --git a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-toolbar-actions.component.mock.ts b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-toolbar-actions.component.mock.ts index f3deda5458..99230013f8 100644 --- a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-toolbar-actions.component.mock.ts +++ b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-toolbar-actions.component.mock.ts @@ -19,11 +19,12 @@ import { Component } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { ViewerComponent } from '../viewer.component'; +import { ViewerToolbarActionsComponent } from '../viewer-toolbar-actions.component'; @Component({ selector: 'adf-viewer-container-toolbar-actions', standalone: true, - imports: [ViewerComponent, MatIconModule, MatButtonModule], + imports: [ViewerComponent, MatIconModule, MatButtonModule, ViewerToolbarActionsComponent], template: ` diff --git a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-toolbar.component.mock.ts b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-toolbar.component.mock.ts index 458ef1a6d7..94129bc7ba 100644 --- a/lib/core/src/lib/viewer/components/mock/adf-viewer-container-toolbar.component.mock.ts +++ b/lib/core/src/lib/viewer/components/mock/adf-viewer-container-toolbar.component.mock.ts @@ -17,11 +17,12 @@ import { Component } from '@angular/core'; import { ViewerComponent } from '../viewer.component'; +import { ViewerToolbarComponent } from '../viewer-toolbar.component'; @Component({ selector: 'adf-viewer-container-toolbar', standalone: true, - imports: [ViewerComponent], + imports: [ViewerComponent, ViewerToolbarComponent], template: ` diff --git a/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts b/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts index 8495365844..456176e302 100644 --- a/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts +++ b/lib/core/src/lib/viewer/components/pdf-viewer/pdf-viewer.component.spec.ts @@ -33,11 +33,14 @@ declare const pdfjsLib: any; @Component({ selector: 'adf-test-dialog-component', + standalone: true, template: '' }) class TestDialogComponent {} @Component({ + standalone: true, + imports: [PdfViewerComponent], template: ` ` }) class UrlTestComponent { @@ -52,6 +55,8 @@ class UrlTestComponent { } @Component({ + standalone: true, + imports: [PdfViewerComponent], template: ` ` }) class UrlTestPasswordComponent { @@ -66,6 +71,8 @@ class UrlTestPasswordComponent { } @Component({ + standalone: true, + imports: [PdfViewerComponent], template: ` ` }) class BlobTestComponent { @@ -105,10 +112,9 @@ describe('Test PdfViewer component', () => { let change: any; let dialog: MatDialog; - beforeEach((done) => { + beforeEach(async () => { TestBed.configureTestingModule({ - imports: [CoreTestingModule], - declarations: [TestDialogComponent, UrlTestComponent, UrlTestPasswordComponent, BlobTestComponent], + imports: [CoreTestingModule, UrlTestComponent, TestDialogComponent, UrlTestPasswordComponent, BlobTestComponent], providers: [ { provide: MatDialog, @@ -129,9 +135,7 @@ describe('Test PdfViewer component', () => { component.inputPage('1'); fixture.detectChanges(); - fixture.whenStable().then(() => { - done(); - }); + await fixture.whenStable(); }); describe('User interaction', () => { @@ -371,28 +375,6 @@ describe('Test PdfViewer component', () => { }); }); }, 55000); - - it('should check if page fits to documentContainer', (done) => { - spyOn(componentUrlTestComponent.pdfViewerComponent, 'checkPageFitInContainer'); - componentUrlTestComponent.pdfViewerComponent.scalePage('auto'); - - fixtureUrlTestComponent.detectChanges(); - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.checkPageFitInContainer).toHaveBeenCalled(); - done(); - }); - }); - - it('should check if document has overflow', (done) => { - spyOn(componentUrlTestComponent.pdfViewerComponent, 'setScaleUpdatePages'); - componentUrlTestComponent.pdfViewerComponent.scalePage('auto'); - - fixtureUrlTestComponent.detectChanges(); - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.setScaleUpdatePages).toHaveBeenCalled(); - done(); - }); - }); }); }); @@ -425,14 +407,13 @@ describe('Test PdfViewer component', () => { document.body.removeChild(elementUrlTestComponent); }); - it('should use the custom zoom if it is present in the app.config', (done) => { + it('should use the custom zoom if it is present in the app.config', async () => { spyOn(componentUrlTestComponent.pdfViewerComponent.pdfViewer, 'forceRendering').and.callFake(() => {}); fixtureUrlTestComponent.detectChanges(); - fixtureUrlTestComponent.whenStable().then(() => { - expect(componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScale).toBe(0.8); - done(); - }); + await fixtureUrlTestComponent.whenStable(); + + expect(componentUrlTestComponent.pdfViewerComponent.pdfViewer.currentScale).toBe(0.8); }); }); @@ -531,15 +512,12 @@ describe('Test PdfViewer component', () => { let fixtureUrlTestComponent: ComponentFixture; let elementUrlTestComponent: HTMLElement; - beforeEach((done) => { + beforeEach(async () => { fixtureUrlTestComponent = TestBed.createComponent(UrlTestComponent); elementUrlTestComponent = fixtureUrlTestComponent.nativeElement; fixtureUrlTestComponent.detectChanges(); - - fixtureUrlTestComponent.whenStable().then(() => { - done(); - }); + await fixtureUrlTestComponent.whenStable(); }); afterEach(() => { @@ -586,15 +564,12 @@ describe('Test PdfViewer component', () => { let fixtureBlobTestComponent: ComponentFixture; let elementBlobTestComponent: HTMLElement; - beforeEach((done) => { + beforeEach(async () => { fixtureBlobTestComponent = TestBed.createComponent(BlobTestComponent); elementBlobTestComponent = fixtureBlobTestComponent.nativeElement; fixtureBlobTestComponent.detectChanges(); - - fixtureBlobTestComponent.whenStable().then(() => { - done(); - }); + await fixtureBlobTestComponent.whenStable(); }); afterEach(() => { @@ -681,44 +656,38 @@ describe('Test PdfViewer component', () => { document.body.removeChild(fixtureUrlTestPasswordComponent.nativeElement); }); - it('should try to access protected pdf', (done) => { + it('should try to access protected pdf', async () => { + componentUrlTestPasswordComponent.pdfViewerComponent.onPdfPassword(() => {}, pdfjsLib.PasswordResponses.NEED_PASSWORD); + + fixture.detectChanges(); + await fixture.whenStable(); + + expect(dialog.open).toHaveBeenCalledTimes(1); + }); + + it('should raise dialog asking for password', async () => { componentUrlTestPasswordComponent.pdfViewerComponent.onPdfPassword(() => {}, pdfjsLib.PasswordResponses.NEED_PASSWORD); fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); + await fixture.whenStable(); - expect(dialog.open).toHaveBeenCalledTimes(1); - done(); + fixture.detectChanges(); + expect(dialog.open['calls'].all()[0].args[1].data).toEqual({ + reason: pdfjsLib.PasswordResponses.NEED_PASSWORD }); }); - it('should raise dialog asking for password', (done) => { - componentUrlTestPasswordComponent.pdfViewerComponent.onPdfPassword(() => {}, pdfjsLib.PasswordResponses.NEED_PASSWORD); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(dialog.open['calls'].all()[0].args[1].data).toEqual({ - reason: pdfjsLib.PasswordResponses.NEED_PASSWORD - }); - done(); - }); - }); - - it('it should raise dialog with incorrect password', (done) => { + it('it should raise dialog with incorrect password', async () => { componentUrlTestPasswordComponent.pdfViewerComponent.onPdfPassword(() => {}, pdfjsLib.PasswordResponses.INCORRECT_PASSWORD); fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(dialog.open['calls'].all()[0].args[1].data).toEqual({ - reason: pdfjsLib.PasswordResponses.INCORRECT_PASSWORD - }); - done(); + await fixture.whenStable(); + expect(dialog.open['calls'].all()[0].args[1].data).toEqual({ + reason: pdfjsLib.PasswordResponses.INCORRECT_PASSWORD }); }); }); describe('Close password dialog ', () => { - beforeEach((done) => { + beforeEach(async () => { fixtureUrlTestPasswordComponent = TestBed.createComponent(UrlTestPasswordComponent); componentUrlTestPasswordComponent = fixtureUrlTestPasswordComponent.componentInstance; @@ -732,25 +701,18 @@ describe('Test PdfViewer component', () => { spyOn(componentUrlTestPasswordComponent.pdfViewerComponent.close, 'emit'); fixtureUrlTestPasswordComponent.detectChanges(); - - fixtureUrlTestPasswordComponent.whenStable().then(() => { - done(); - }); + await fixtureUrlTestPasswordComponent.whenStable(); }); afterEach(() => { document.body.removeChild(fixtureUrlTestPasswordComponent.nativeElement); }); - it('should try to access protected pdf', (done) => { + it('should try to access protected pdf', async () => { componentUrlTestPasswordComponent.pdfViewerComponent.onPdfPassword(() => {}, pdfjsLib.PasswordResponses.NEED_PASSWORD); fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - - expect(componentUrlTestPasswordComponent.pdfViewerComponent.close.emit).toHaveBeenCalledWith(); - done(); - }); + await fixture.whenStable(); + expect(componentUrlTestPasswordComponent.pdfViewerComponent.close.emit).toHaveBeenCalledWith(); }); }); }); diff --git a/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts b/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts index ffde296d98..39f042adad 100644 --- a/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts +++ b/lib/core/src/lib/viewer/components/viewer-render/viewer-render.component.spec.ts @@ -20,16 +20,18 @@ import { Location } from '@angular/common'; import { SpyLocation } from '@angular/common/testing'; import { Component, TemplateRef, ViewChild } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatButtonModule } from '@angular/material/button'; -import { MatDialog } from '@angular/material/dialog'; -import { MatIconModule } from '@angular/material/icon'; +import { MatDialog, MatDialogModule } from '@angular/material/dialog'; import { By } from '@angular/platform-browser'; -import { CoreTestingModule } from '../../../testing'; +import { NoopTranslateModule } from '../../../testing'; import { RenderingQueueServices } from '../../services/rendering-queue.services'; import { ViewerRenderComponent } from './viewer-render.component'; +import { ViewerExtensionDirective } from '@alfresco/adf-core'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @Component({ selector: 'adf-double-viewer', + standalone: true, + imports: [ViewerExtensionDirective, ViewerRenderComponent], template: ` @@ -70,8 +72,7 @@ describe('ViewerComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [CoreTestingModule, MatButtonModule, MatIconModule], - declarations: [DoubleViewerComponent], + imports: [NoopTranslateModule, NoopAnimationsModule, MatDialogModule, ViewerRenderComponent, DoubleViewerComponent], providers: [RenderingQueueServices, { provide: Location, useClass: SpyLocation }, MatDialog] }); fixture = TestBed.createComponent(ViewerRenderComponent); diff --git a/lib/core/test.ts b/lib/core/test.ts index 3836ebfb6a..d0723f8e8a 100644 --- a/lib/core/test.ts +++ b/lib/core/test.ts @@ -22,5 +22,5 @@ import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@ang // First, initialize the Angular testing environment. getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { - teardown: { destroyAfterEach: false } + teardown: { destroyAfterEach: true } }); diff --git a/lib/extensions/src/test.ts b/lib/extensions/src/test.ts index c5508f0ae1..b1f00fb4ca 100644 --- a/lib/extensions/src/test.ts +++ b/lib/extensions/src/test.ts @@ -24,5 +24,5 @@ import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@ang // First, initialize the Angular testing environment. getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { - teardown: { destroyAfterEach: false } + teardown: { destroyAfterEach: true } }); diff --git a/lib/process-services/src/lib/app-list/select-apps-dialog/select-apps-dialog.component.spec.ts b/lib/process-services/src/lib/app-list/select-apps-dialog/select-apps-dialog.component.spec.ts index 4c1fcc111e..683c0d0452 100644 --- a/lib/process-services/src/lib/app-list/select-apps-dialog/select-apps-dialog.component.spec.ts +++ b/lib/process-services/src/lib/app-list/select-apps-dialog/select-apps-dialog.component.spec.ts @@ -42,7 +42,7 @@ export class DialogSelectAppTestComponent { }); this.dialogRef.afterClosed().subscribe((selectedProcess) => { - this.processId = selectedProcess.id; + this.processId = selectedProcess?.id; }); } } diff --git a/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget-dialog.component.spec.ts b/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget-dialog.component.spec.ts index 269a837d3f..7f6b6e6a04 100644 --- a/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget-dialog.component.spec.ts +++ b/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget-dialog.component.spec.ts @@ -17,13 +17,13 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { AlfrescoApiService, ContentModule, ContentNodeSelectorPanelComponent, DocumentListService, SitesService, NodesApiService } from '@alfresco/adf-content-services'; +import { ContentNodeSelectorPanelComponent, DocumentListService, SitesService, NodesApiService } from '@alfresco/adf-content-services'; import { EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core'; import { ProcessTestingModule } from '../../../testing/process.testing.module'; import { AttachFileWidgetDialogComponent } from './attach-file-widget-dialog.component'; -import { BasicAlfrescoAuthService, OidcAuthenticationService } from '@alfresco/adf-core'; +import { AuthenticationService } from '@alfresco/adf-core'; import { AttachFileWidgetDialogComponentData } from './attach-file-widget-dialog-component.interface'; -import { of, throwError } from 'rxjs'; +import { of, Subject, throwError } from 'rxjs'; import { By } from '@angular/platform-browser'; import { Node, SiteEntry, NodeEntry, SitePaging, SitePagingList } from '@alfresco/js-api'; @@ -39,21 +39,19 @@ describe('AttachFileWidgetDialogComponent', () => { isSelectionValid: (entry: Node) => entry.isFile }; let element: HTMLInputElement; - let basicAlfrescoAuthService: BasicAlfrescoAuthService; let siteService: SitesService; let nodeService: NodesApiService; let documentListService: DocumentListService; - let apiService: AlfrescoApiService; - let matDialogRef: MatDialogRef; + let isLoggedInSpy: jasmine.Spy; + let authService: AuthenticationService; + let closeSpy: jasmine.Spy; - let isLogged = false; const fakeSite = new SiteEntry({ entry: { id: 'fake-site', guid: 'fake-site', title: 'fake-site', visibility: 'visible' } }); beforeEach(() => { TestBed.configureTestingModule({ - imports: [ContentModule.forRoot(), ProcessTestingModule, AttachFileWidgetDialogComponent], + imports: [ProcessTestingModule, AttachFileWidgetDialogComponent], providers: [ - { provide: OidcAuthenticationService, useValue: {} }, { provide: MAT_DIALOG_DATA, useValue: data }, { provide: MatDialogRef, useValue: { close: () => of() } } ], @@ -62,12 +60,16 @@ describe('AttachFileWidgetDialogComponent', () => { fixture = TestBed.createComponent(AttachFileWidgetDialogComponent); widget = fixture.componentInstance; element = fixture.nativeElement; - basicAlfrescoAuthService = fixture.debugElement.injector.get(BasicAlfrescoAuthService); siteService = fixture.debugElement.injector.get(SitesService); nodeService = fixture.debugElement.injector.get(NodesApiService); documentListService = fixture.debugElement.injector.get(DocumentListService); - matDialogRef = fixture.debugElement.injector.get(MatDialogRef); - apiService = fixture.debugElement.injector.get(AlfrescoApiService); + + const matDialogRef = fixture.debugElement.injector.get(MatDialogRef); + closeSpy = spyOn(matDialogRef, 'close'); + + authService = fixture.debugElement.injector.get(AuthenticationService); + spyOn(authService, 'login').and.returnValue(of({ type: 'type', ticket: 'ticket' })); + authService.onLogin = new Subject(); spyOn(documentListService, 'getFolderNode').and.returnValue(of({ entry: { path: { elements: [] } } } as NodeEntry)); spyOn(documentListService, 'getFolder').and.returnValue(throwError('No results for test')); @@ -77,22 +79,17 @@ describe('AttachFileWidgetDialogComponent', () => { spyOn(siteService, 'getSite').and.returnValue(of(fakeSite)); spyOn(siteService, 'getSites').and.returnValue(of(new SitePaging({ list: new SitePagingList({ entries: [] }) }))); - spyOn(widget, 'isLoggedIn').and.callFake(() => isLogged); + isLoggedInSpy = spyOn(widget, 'isLoggedIn').and.returnValue(false); }); afterEach(() => { fixture.destroy(); }); - it('should be able to create the widget', () => { - fixture.detectChanges(); - expect(widget).not.toBeNull(); - }); - describe('When is not logged in', () => { beforeEach(() => { + isLoggedInSpy.and.returnValue(false); fixture.detectChanges(); - isLogged = false; }); it('should show the login form', () => { @@ -103,8 +100,7 @@ describe('AttachFileWidgetDialogComponent', () => { }); it('should be able to login', (done) => { - spyOn(basicAlfrescoAuthService, 'login').and.returnValue(of({ type: 'type', ticket: 'ticket' })); - isLogged = true; + isLoggedInSpy.and.returnValue(true); let loginButton: HTMLButtonElement = element.querySelector('[data-automation-id="attach-file-dialog-actions-login"]'); const usernameInput: HTMLInputElement = element.querySelector('#username'); const passwordInput: HTMLInputElement = element.querySelector('#password'); @@ -129,7 +125,7 @@ describe('AttachFileWidgetDialogComponent', () => { let contentNodePanel; beforeEach(() => { - isLogged = true; + isLoggedInSpy.and.returnValue(true); fixture.detectChanges(); contentNodePanel = fixture.debugElement.query(By.directive(ContentNodeSelectorPanelComponent)); }); @@ -181,43 +177,36 @@ describe('AttachFileWidgetDialogComponent', () => { describe('login only', () => { beforeEach(() => { - spyOn(basicAlfrescoAuthService, 'login').and.returnValue(of({ type: 'type', ticket: 'ticket' })); - spyOn(matDialogRef, 'close').and.callThrough(); - fixture.detectChanges(); - widget.data.loginOnly = true; - widget.data.registerExternalHost = () => {}; - isLogged = false; + widget.data = { + ...widget.data, + loginOnly: true, + registerExternalHost: () => {} + }; }); - it('should close the dialog once user loggedIn', () => { + it('should close the dialog once user loggedIn', async () => { + isLoggedInSpy.and.returnValue(false); fixture.detectChanges(); - isLogged = true; - const loginButton = element.querySelector('[data-automation-id="attach-file-dialog-actions-login"]'); - const usernameInput = element.querySelector('#username'); - const passwordInput = element.querySelector('#password'); - usernameInput.value = 'fake-user'; - passwordInput.value = 'fake-user'; - usernameInput.dispatchEvent(new Event('input')); - passwordInput.dispatchEvent(new Event('input')); - loginButton.click(); - basicAlfrescoAuthService.onLogin.next('logged-in'); + authService.onLogin.next('logged-in'); + fixture.detectChanges(); - expect(matDialogRef.close).toHaveBeenCalled(); + await fixture.whenStable(); + + expect(closeSpy).toHaveBeenCalled(); }); it('should close the dialog immediately if user already loggedIn', () => { - isLogged = true; + isLoggedInSpy.and.returnValue(true); fixture.detectChanges(); - spyOn(apiService, 'getInstance').and.returnValue({ isLoggedIn: () => true } as any); - widget.updateExternalHost(); - expect(matDialogRef.close).toHaveBeenCalled(); + fixture.componentInstance.ngOnInit(); + expect(closeSpy).toHaveBeenCalled(); }); }); describe('Attach button', () => { beforeEach(() => { - isLogged = true; + isLoggedInSpy.and.returnValue(true); }); it('should be disabled by default', () => { diff --git a/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget-dialog.component.ts b/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget-dialog.component.ts index f05582bff7..ac23c61967 100644 --- a/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget-dialog.component.ts +++ b/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget-dialog.component.ts @@ -15,16 +15,24 @@ * limitations under the License. */ -import { Component, Inject, ViewEncapsulation, ViewChild } from '@angular/core'; +import { Component, Inject, ViewEncapsulation, ViewChild, OnDestroy, OnInit } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { LoginDialogPanelComponent, TranslationService, AuthenticationService } from '@alfresco/adf-core'; import { AttachFileWidgetDialogComponentData } from './attach-file-widget-dialog-component.interface'; -import { DocumentListService, SitesService, SearchService, ContentNodeSelectorPanelComponent, AlfrescoApiService } from '@alfresco/adf-content-services'; +import { + DocumentListService, + SitesService, + SearchService, + ContentNodeSelectorPanelComponent, + AlfrescoApiService +} from '@alfresco/adf-content-services'; import { ExternalAlfrescoApiService } from '../../services/external-alfresco-api.service'; import { Node } from '@alfresco/js-api'; import { CommonModule } from '@angular/common'; import { MatButtonModule } from '@angular/material/button'; import { TranslateModule } from '@ngx-translate/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'adf-attach-file-widget-dialog', @@ -41,7 +49,7 @@ import { TranslateModule } from '@ngx-translate/core'; { provide: AlfrescoApiService, useClass: ExternalAlfrescoApiService } ] }) -export class AttachFileWidgetDialogComponent { +export class AttachFileWidgetDialogComponent implements OnInit, OnDestroy { @ViewChild('adfLoginPanel') loginPanel: LoginDialogPanelComponent; @@ -50,6 +58,8 @@ export class AttachFileWidgetDialogComponent { buttonActionName: string; chosenNode: Node[]; + private onDestroy$ = new Subject(); + constructor( private translation: TranslationService, @Inject(MAT_DIALOG_DATA) public data: AttachFileWidgetDialogComponentData, @@ -61,16 +71,21 @@ export class AttachFileWidgetDialogComponent { this.action = data.actionName ? data.actionName.toUpperCase() : 'CHOOSE'; this.buttonActionName = `ATTACH-FILE.ACTIONS.${this.action}`; this.updateTitle('DROPDOWN.MY_FILES_OPTION'); - this.updateExternalHost(); } - updateExternalHost() { - this.authenticationService.onLogin.subscribe(() => this.registerAndClose()); + ngOnInit() { + this.authenticationService.onLogin.pipe(takeUntil(this.onDestroy$)).subscribe(() => this.registerAndClose()); + if (this.isLoggedIn()) { this.registerAndClose(); } } + ngOnDestroy() { + this.onDestroy$.next(true); + this.onDestroy$.complete(); + } + isLoggedIn(): boolean { return !!this.externalApiService.getInstance()?.isLoggedIn(); } @@ -111,10 +126,13 @@ export class AttachFileWidgetDialogComponent { } private registerAndClose() { - this.data.registerExternalHost(this.data.accountIdentifier, this.externalApiService); - if (this.data.loginOnly) { - this.data.selected.complete(); - this.matDialogRef.close(); + if (this.data) { + this.data.registerExternalHost?.(this.data.accountIdentifier, this.externalApiService); + + if (this.data.loginOnly) { + this.data.selected?.complete(); + this.matDialogRef.close(); + } } } } diff --git a/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget.component.spec.ts b/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget.component.spec.ts index 2de77f2be4..ca38d93636 100644 --- a/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget.component.spec.ts +++ b/lib/process-services/src/lib/form/widgets/content-widget/attach-file-widget.component.spec.ts @@ -28,7 +28,7 @@ import { AppConfigService, AppConfigValues } from '@alfresco/adf-core'; -import { ContentNodeDialogService, ContentModule } from '@alfresco/adf-content-services'; +import { ContentNodeDialogService } from '@alfresco/adf-content-services'; import { of } from 'rxjs'; import { Node } from '@alfresco/js-api'; import { ProcessTestingModule } from '../../../testing/process.testing.module'; @@ -154,7 +154,7 @@ describe('AttachFileWidgetComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [ProcessTestingModule, ContentModule.forRoot()] + imports: [ProcessTestingModule, AttachFileWidgetComponent] }); fixture = TestBed.createComponent(AttachFileWidgetComponent); widget = fixture.componentInstance; diff --git a/lib/process-services/src/lib/people/components/people/people.component.spec.ts b/lib/process-services/src/lib/people/components/people/people.component.spec.ts index 39a158df10..12cf893d49 100644 --- a/lib/process-services/src/lib/people/components/people/people.component.spec.ts +++ b/lib/process-services/src/lib/people/components/people/people.component.spec.ts @@ -15,12 +15,12 @@ * limitations under the License. */ -import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { PeopleComponent } from './people.component'; import { ProcessTestingModule } from '../../../testing/process.testing.module'; import { LightUserRepresentation } from '@alfresco/js-api'; - -declare let jasmine: any; +import { PeopleProcessService } from '@alfresco/adf-process-services'; +import { of, throwError } from 'rxjs'; const fakeUser: LightUserRepresentation = { id: 0, @@ -40,19 +40,24 @@ describe('PeopleComponent', () => { let peopleComponent: PeopleComponent; let fixture: ComponentFixture; let element: HTMLElement; - const userArray = [fakeUser, fakeSecondUser]; + let peopleProcessService: PeopleProcessService; + let userArray: LightUserRepresentation[]; beforeEach(() => { TestBed.configureTestingModule({ imports: [ProcessTestingModule, PeopleComponent] }); fixture = TestBed.createComponent(PeopleComponent); + peopleProcessService = fixture.debugElement.injector.get(PeopleProcessService); + peopleComponent = fixture.componentInstance; element = fixture.nativeElement; peopleComponent.people = []; peopleComponent.readOnly = true; fixture.detectChanges(); + + userArray = [fakeUser, fakeSecondUser]; }); afterEach(() => fixture.destroy()); @@ -78,18 +83,10 @@ describe('PeopleComponent', () => { describe('when there are involved people', () => { beforeEach(() => { peopleComponent.taskId = 'fake-task-id'; - peopleComponent.people.push(...userArray); + peopleComponent.people = [...userArray]; fixture.detectChanges(); }); - beforeEach(() => { - jasmine.Ajax.install(); - }); - - afterEach(() => { - jasmine.Ajax.uninstall(); - }); - it('should show people involved', async () => { fixture.detectChanges(); await fixture.whenStable(); @@ -99,33 +96,73 @@ describe('PeopleComponent', () => { expect(gatewayElement.children.length).toBe(2); }); - it('should remove people involved', fakeAsync(() => { - peopleComponent.removeInvolvedUser(fakeUser); - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200 - }); - fixture.whenStable().then(() => { - fixture.detectChanges(); - const gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); - expect(gatewayElement).not.toBeNull(); - expect(gatewayElement.children.length).toBe(1); - }); - })); + it('should remove involved user successfully', () => { + spyOn(peopleProcessService, 'removeInvolvedUser').and.returnValue(of(null)); + peopleComponent.people = [...userArray]; + + peopleComponent.removeInvolvedUser(fakeUser); + + fixture.detectChanges(); + + expect(peopleComponent.people.length).toBe(1); + expect(peopleComponent.people.find((user) => user.id === fakeUser.id)).toBeUndefined(); + }); + + it('should emit error when removing involved user fails', () => { + spyOn(peopleProcessService, 'removeInvolvedUser').and.returnValue(throwError(() => new Error('error'))); + spyOn(peopleComponent.error, 'emit'); + peopleComponent.people = [...userArray]; + + peopleComponent.removeInvolvedUser(fakeUser); + + fixture.detectChanges(); + + expect(peopleComponent.people.length).toBe(2); + expect(peopleComponent.error.emit).toHaveBeenCalledWith('Impossible to remove involved user from task'); + }); + + it('should involve user successfully', () => { + spyOn(peopleProcessService, 'involveUserWithTask').and.returnValue(of(null)); + peopleComponent.people = [...userArray]; - it('should involve people', fakeAsync(() => { peopleComponent.involveUser(fakeUser); - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200 - }); - fixture.whenStable().then(() => { - fixture.detectChanges(); - const gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); - expect(gatewayElement).not.toBeNull(); - expect(gatewayElement.children.length).toBe(3); - }); - })); + + fixture.detectChanges(); + + expect(peopleComponent.people.length).toBe(3); + expect(peopleComponent.people.find((user) => user.id === fakeUser.id)).toBeDefined(); + }); + + it('should emit error when involving user fails', () => { + spyOn(peopleProcessService, 'involveUserWithTask').and.returnValue(throwError(() => new Error('error'))); + spyOn(peopleComponent.error, 'emit'); + peopleComponent.people = [...userArray]; + + peopleComponent.involveUser(fakeUser); + + fixture.detectChanges(); + + expect(peopleComponent.people.length).toBe(2); + expect(peopleComponent.error.emit).toHaveBeenCalledWith('Impossible to involve user with task'); + }); it('should return an observable with user search results', (done) => { + spyOn(peopleProcessService, 'getWorkflowUsers').and.returnValue( + of([ + { + id: 1, + firstName: 'fake-test-1', + lastName: 'fake-last-1', + email: 'fake-test-1@test.com' + }, + { + id: 2, + firstName: 'fake-test-2', + lastName: 'fake-last-2', + email: 'fake-test-2@test.com' + } + ]) + ); peopleComponent.peopleSearch$.subscribe((users) => { expect(users.length).toBe(2); expect(users[0].firstName).toBe('fake-test-1'); @@ -135,71 +172,44 @@ describe('PeopleComponent', () => { done(); }); peopleComponent.searchUser('fake-search-word'); - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: { - data: [ - { - id: 1, - firstName: 'fake-test-1', - lastName: 'fake-last-1', - email: 'fake-test-1@test.com' - }, - { - id: 2, - firstName: 'fake-test-2', - lastName: 'fake-last-2', - email: 'fake-test-2@test.com' - } - ] - } - }); }); it('should return an empty list for not valid search', (done) => { + spyOn(peopleProcessService, 'getWorkflowUsers').and.returnValue(of([])); peopleComponent.peopleSearch$.subscribe((users) => { expect(users.length).toBe(0); done(); }); peopleComponent.searchUser('fake-search-word'); - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 200, - contentType: 'json', - responseText: {} - }); }); }); describe('when there are errors on service call', () => { beforeEach(() => { - jasmine.Ajax.install(); peopleComponent.people.push(...userArray); fixture.detectChanges(); }); - afterEach(() => { - jasmine.Ajax.uninstall(); - }); - it('should not remove user if remove involved user fail', async () => { + spyOn(peopleProcessService, 'removeInvolvedUser').and.returnValue(throwError(() => new Error('error'))); peopleComponent.removeInvolvedUser(fakeUser); - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 403 - }); + + fixture.detectChanges(); await fixture.whenStable(); - const gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); + + const gatewayElement = element.querySelector('#assignment-people-list .adf-datatable-body'); expect(gatewayElement).not.toBeNull(); expect(gatewayElement.children.length).toBe(2); }); it('should not involve user if involve user fail', async () => { + spyOn(peopleProcessService, 'involveUserWithTask').and.returnValue(throwError(() => new Error('error'))); peopleComponent.involveUser(fakeUser); - jasmine.Ajax.requests.mostRecent().respondWith({ - status: 403 - }); + + fixture.detectChanges(); await fixture.whenStable(); - const gatewayElement: any = element.querySelector('#assignment-people-list .adf-datatable-body'); + + const gatewayElement = element.querySelector('#assignment-people-list .adf-datatable-body'); expect(gatewayElement).not.toBeNull(); expect(gatewayElement.children.length).toBe(2); }); diff --git a/lib/process-services/src/lib/people/components/people/people.component.ts b/lib/process-services/src/lib/people/components/people/people.component.ts index ee85875d80..ce313aed6a 100644 --- a/lib/process-services/src/lib/people/components/people/people.component.ts +++ b/lib/process-services/src/lib/people/components/people/people.component.ts @@ -75,30 +75,30 @@ export class PeopleComponent { } searchUser(searchedWord: string) { - this.peopleProcessService.getWorkflowUsers(this.taskId, searchedWord).subscribe( - (users) => { + this.peopleProcessService.getWorkflowUsers(this.taskId, searchedWord).subscribe({ + next: (users) => { this.peopleSearchObserver.next(users); }, - (error) => this.error.emit(error) - ); + error: (error) => this.error.emit(error) + }); } involveUser(user: LightUserRepresentation) { if (user?.id !== undefined) { - this.peopleProcessService.involveUserWithTask(this.taskId, user.id.toString()).subscribe( - () => (this.people = [...this.people, user]), - () => this.error.emit('Impossible to involve user with task') - ); + this.peopleProcessService.involveUserWithTask(this.taskId, user.id.toString()).subscribe({ + next: () => (this.people = [...this.people, user]), + error: () => this.error.emit('Impossible to involve user with task') + }); } } removeInvolvedUser(user: LightUserRepresentation) { - this.peopleProcessService.removeInvolvedUser(this.taskId, user.id.toString()).subscribe( - () => { + this.peopleProcessService.removeInvolvedUser(this.taskId, user.id.toString()).subscribe({ + next: () => { this.people = this.people.filter((involvedUser) => involvedUser.id !== user.id); }, - () => this.error.emit('Impossible to remove involved user from task') - ); + error: () => this.error.emit('Impossible to remove involved user from task') + }); } getDisplayUser(firstName: string, lastName: string, delimiter: string = '-'): string { diff --git a/lib/process-services/src/lib/process-list/components/process-filters/process-filters.component.spec.ts b/lib/process-services/src/lib/process-list/components/process-filters/process-filters.component.spec.ts index dd5e1084a9..ab86acb7eb 100644 --- a/lib/process-services/src/lib/process-list/components/process-filters/process-filters.component.spec.ts +++ b/lib/process-services/src/lib/process-list/components/process-filters/process-filters.component.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { CUSTOM_ELEMENTS_SCHEMA, SimpleChange } from '@angular/core'; +import { SimpleChange } from '@angular/core'; import { from, of, throwError } from 'rxjs'; import { AppsProcessService } from '../../../services/apps-process.service'; import { ProcessFilterService } from '../../services/process-filter.service'; @@ -24,7 +24,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { ProcessTestingModule } from '../../../testing/process.testing.module'; import { NavigationStart, Router } from '@angular/router'; -import { RouterTestingModule } from '@angular/router/testing'; import { ProcessInstanceFilterRepresentation, UserProcessInstanceFilterRepresentation } from '@alfresco/js-api'; const fakeProcessFilters: UserProcessInstanceFilterRepresentation[] = [ @@ -54,17 +53,26 @@ describe('ProcessFiltersComponent', () => { let processFilterService: ProcessFilterService; let appsProcessService: AppsProcessService; let router: Router; + let getProcessFiltersSpy: jasmine.Spy; + let getDeployedApplicationsByNameSpy: jasmine.Spy; beforeEach(() => { TestBed.configureTestingModule({ - imports: [ProcessTestingModule, RouterTestingModule], - schemas: [CUSTOM_ELEMENTS_SCHEMA] + imports: [ProcessTestingModule] }); + + processFilterService = TestBed.inject(ProcessFilterService); + getProcessFiltersSpy = spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); + + appsProcessService = TestBed.inject(AppsProcessService); + getDeployedApplicationsByNameSpy = spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue( + from(Promise.resolve({ id: 1 })) + ); + + router = TestBed.inject(Router); + fixture = TestBed.createComponent(ProcessFiltersComponent); filterList = fixture.componentInstance; - processFilterService = TestBed.inject(ProcessFilterService); - appsProcessService = TestBed.inject(AppsProcessService); - router = TestBed.inject(Router); }); afterEach(() => { @@ -72,7 +80,6 @@ describe('ProcessFiltersComponent', () => { }); it('should return the filter task list', async () => { - spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); const appId = '1'; const change = new SimpleChange(null, appId, true); @@ -97,23 +104,7 @@ describe('ProcessFiltersComponent', () => { expect(filterList.filters[2].name).toEqual('Running'); }); - it('should select the Running process filter', async () => { - spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); - - const appId = '1'; - const change = new SimpleChange(null, appId, true); - - filterList.ngOnChanges({ appId: change }); - - fixture.detectChanges(); - await fixture.whenStable(); - - filterList.selectRunningFilter(); - expect(filterList.currentFilter.name).toEqual('Running'); - }); - it('should emit the selected filter based on the filterParam input', async () => { - spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); filterList.filterParam = { id: 10 } as any; const appId = '1'; const change = new SimpleChange(null, appId, true); @@ -142,8 +133,6 @@ describe('ProcessFiltersComponent', () => { }); it('should reset selection when filterParam is a filter that does not exist', async () => { - spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); - const nonExistingFilterParam = { name: 'non-existing-filter' }; const appId = '1'; const change = new SimpleChange(null, appId, true); @@ -159,18 +148,15 @@ describe('ProcessFiltersComponent', () => { }); it('should return the filter task list, filtered By Name', () => { - const deployApp = spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(from(Promise.resolve({ id: 1 }))); - spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); - const change = new SimpleChange(null, 'test', true); filterList.ngOnChanges({ appName: change }); fixture.detectChanges(); - expect(deployApp.calls.count()).toEqual(1); + expect(getDeployedApplicationsByNameSpy.calls.count()).toEqual(1); }); it('should emit an error with a bad response of getProcessFilters', () => { - spyOn(processFilterService, 'getProcessFilters').and.returnValue(throwError('error')); + getProcessFiltersSpy.and.returnValue(throwError(() => new Error('error'))); const appId = '1'; const change = new SimpleChange(null, appId, true); @@ -184,7 +170,7 @@ describe('ProcessFiltersComponent', () => { }); it('should emit an error with a bad response of getDeployedApplicationsByName', () => { - spyOn(appsProcessService, 'getDeployedApplicationsByName').and.returnValue(throwError('wrong request')); + getDeployedApplicationsByNameSpy.and.returnValue(throwError(() => new Error('wrong request'))); const appId = 'fake-app'; const change = new SimpleChange(null, appId, true); @@ -255,8 +241,6 @@ describe('ProcessFiltersComponent', () => { }); it('should select the filter passed as input by id', async () => { - spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); - filterList.filterParam = { id: 20 } as any; const appId = 1; @@ -272,8 +256,6 @@ describe('ProcessFiltersComponent', () => { }); it('should select the filter passed as input by name', async () => { - spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); - filterList.filterParam = { name: 'FakeAll' } as any; const appId = 1; @@ -289,7 +271,6 @@ describe('ProcessFiltersComponent', () => { }); it('should attach specific icon for each filter if hasIcon is true', async () => { - spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); filterList.showIcon = true; const change = new SimpleChange(undefined, 1, true); filterList.ngOnChanges({ appId: change }); @@ -304,7 +285,6 @@ describe('ProcessFiltersComponent', () => { }); it('should not attach icons for each filter if hasIcon is false', async () => { - spyOn(processFilterService, 'getProcessFilters').and.returnValue(of(fakeProcessFilters)); filterList.showIcon = false; const change = new SimpleChange(undefined, 1, true); filterList.ngOnChanges({ appId: change }); diff --git a/lib/process-services/src/lib/task-list/components/task-details/task-details.component.spec.ts b/lib/process-services/src/lib/task-list/components/task-details/task-details.component.spec.ts index 85830cd773..1c468a418b 100644 --- a/lib/process-services/src/lib/task-list/components/task-details/task-details.component.spec.ts +++ b/lib/process-services/src/lib/task-list/components/task-details/task-details.component.spec.ts @@ -15,18 +15,17 @@ * limitations under the License. */ -import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core'; +import { SimpleChange } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { of, throwError } from 'rxjs'; -import { FormModel, FormOutcomeEvent, FormOutcomeModel, CommentModel, User } from '@alfresco/adf-core'; +import { FormModel, FormOutcomeEvent, FormOutcomeModel, CommentModel, User, ADF_COMMENTS_SERVICE, CommentsService } from '@alfresco/adf-core'; import { noDataMock, taskDetailsMock, taskFormMock, tasksMock, taskDetailsWithOutAssigneeMock } from '../../../testing/mock'; import { TaskListService } from '../../services/tasklist.service'; import { TaskDetailsComponent } from './task-details.component'; import { ProcessTestingModule } from '../../../testing/process.testing.module'; import { TaskService } from '../../../form/services/task.service'; import { TaskFormService } from '../../../form/services/task-form.service'; -import { TaskCommentsService } from '../../../services/task-comments.service'; import { PeopleProcessService } from '../../../services/people-process.service'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { HarnessLoader } from '@angular/cdk/testing'; @@ -48,32 +47,27 @@ const fakeTaskAssignResponse: any = { }; describe('TaskDetailsComponent', () => { - let taskListService: TaskListService; - let taskService: TaskService; let taskFormService: TaskFormService; let component: TaskDetailsComponent; let fixture: ComponentFixture; let loader: HarnessLoader; let getTaskDetailsSpy: jasmine.Spy; - let getCommentsSpy: jasmine.Spy; let getTasksSpy: jasmine.Spy; let assignTaskSpy: jasmine.Spy; - let taskCommentsService: TaskCommentsService; + let taskCommentsService: CommentsService; let peopleProcessService: PeopleProcessService; beforeEach(() => { TestBed.configureTestingModule({ - imports: [ProcessTestingModule, TaskDetailsComponent], - schemas: [NO_ERRORS_SCHEMA] + imports: [ProcessTestingModule, TaskDetailsComponent] }); peopleProcessService = TestBed.inject(PeopleProcessService); - spyOn(peopleProcessService, 'getCurrentUserInfo').and.returnValue(of({ email: 'fake-email' } as any)); - taskListService = TestBed.inject(TaskListService); + const taskListService = TestBed.inject(TaskListService); spyOn(taskListService, 'getTaskChecklist').and.returnValue(of(noDataMock)); - taskService = TestBed.inject(TaskService); + const taskService = TestBed.inject(TaskService); taskFormService = TestBed.inject(TaskFormService); getTaskDetailsSpy = spyOn(taskListService, 'getTaskDetails').and.returnValue(of(taskDetailsMock)); @@ -83,9 +77,11 @@ describe('TaskDetailsComponent', () => { getTasksSpy = spyOn(taskListService, 'getTasks').and.returnValue(of(tasksMock)); assignTaskSpy = spyOn(taskListService, 'assignTask').and.returnValue(of(fakeTaskAssignResponse)); - taskCommentsService = TestBed.inject(TaskCommentsService); - getCommentsSpy = spyOn(taskCommentsService, 'get').and.returnValue( + fixture = TestBed.createComponent(TaskDetailsComponent); + taskCommentsService = fixture.debugElement.injector.get(ADF_COMMENTS_SERVICE); + + spyOn(taskCommentsService, 'get').and.returnValue( of([ new CommentModel({ message: 'Test1', created: new Date(), createdBy: new User({ firstName: 'Admin', lastName: 'User' }) }), new CommentModel({ message: 'Test2', created: new Date(), createdBy: new User({ firstName: 'Admin', lastName: 'User' }) }), @@ -93,15 +89,12 @@ describe('TaskDetailsComponent', () => { ]) ); - fixture = TestBed.createComponent(TaskDetailsComponent); - peopleProcessService = TestBed.inject(PeopleProcessService); component = fixture.componentInstance; + component.showComments = false; loader = TestbedHarnessEnvironment.documentRootLoader(fixture); }); afterEach(() => { - getTaskDetailsSpy.calls.reset(); - getCommentsSpy.calls.reset(); fixture.destroy(); }); @@ -418,8 +411,12 @@ describe('TaskDetailsComponent', () => { expect(lastValue.length).toBe(0); }); - it('should assign task to user', () => { + it('should assign task to user', async () => { component.assignTaskToUser(fakeUser); + + fixture.detectChanges(); + await fixture.whenStable(); + expect(assignTaskSpy).toHaveBeenCalled(); }); }); diff --git a/lib/process-services/src/lib/task-list/components/task-details/task-details.component.ts b/lib/process-services/src/lib/task-list/components/task-details/task-details.component.ts index e5caceab80..f546ec3acd 100644 --- a/lib/process-services/src/lib/task-list/components/task-details/task-details.component.ts +++ b/lib/process-services/src/lib/task-list/components/task-details/task-details.component.ts @@ -16,6 +16,7 @@ */ import { + ADF_COMMENTS_SERVICE, CardViewUpdateService, ClickNotification, ContentLinkModel, @@ -51,7 +52,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { AttachFormComponent } from '../attach-form/attach-form.component'; import { PeopleComponent, PeopleSearchComponent } from '../../../people'; import { TaskHeaderComponent } from '../task-header/task-header.component'; -import { TaskCommentsComponent } from '../../../task-comments'; +import { TaskCommentsComponent, TaskCommentsService } from '../../../task-comments'; import { ChecklistComponent } from '../checklist/checklist.component'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; @@ -75,6 +76,12 @@ import { MatCardModule } from '@angular/material/card'; InfoDrawerComponent, MatCardModule ], + providers: [ + { + provide: ADF_COMMENTS_SERVICE, + useClass: TaskCommentsService + } + ], templateUrl: './task-details.component.html', styleUrls: ['./task-details.component.scss'], encapsulation: ViewEncapsulation.None diff --git a/lib/process-services/src/lib/testing/process.testing.module.ts b/lib/process-services/src/lib/testing/process.testing.module.ts index 679e11ada2..5a02727c6c 100644 --- a/lib/process-services/src/lib/testing/process.testing.module.ts +++ b/lib/process-services/src/lib/testing/process.testing.module.ts @@ -15,36 +15,19 @@ * limitations under the License. */ -import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-content-services'; import { NgModule } from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { ProcessModule } from '../process.module'; -import { - AppConfigService, - AppConfigServiceMock, - CoreModule, - FormRenderingService, - AuthModule, - NoopTranslateModule -} from '@alfresco/adf-core'; +import { CoreModule, FormRenderingService, NoopTranslateModule, NoopAuthModule } from '@alfresco/adf-core'; import { ProcessFormRenderingService } from '../form/process-form-rendering.service'; -import { RouterTestingModule } from '@angular/router/testing'; +import { AlfrescoApiService, AlfrescoApiServiceMock } from '@alfresco/adf-content-services'; @NgModule({ - imports: [ - AuthModule.forRoot({ useHash: true }), - NoopAnimationsModule, - CoreModule.forRoot(), - ProcessModule.forRoot(), - RouterTestingModule, - NoopTranslateModule - ], + imports: [CoreModule.forRoot(), ProcessModule.forRoot(), NoopAuthModule, NoopAnimationsModule, NoopTranslateModule], providers: [ { provide: AlfrescoApiService, useClass: AlfrescoApiServiceMock }, - { provide: AppConfigService, useClass: AppConfigServiceMock }, - FormRenderingService, { provide: FormRenderingService, useClass: ProcessFormRenderingService } ], - exports: [NoopAnimationsModule, CoreModule, ProcessModule] + exports: [CoreModule, ProcessModule] }) export class ProcessTestingModule {} diff --git a/lib/process-services/src/test.ts b/lib/process-services/src/test.ts index 3836ebfb6a..d0723f8e8a 100644 --- a/lib/process-services/src/test.ts +++ b/lib/process-services/src/test.ts @@ -22,5 +22,5 @@ import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@ang // First, initialize the Angular testing environment. getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { - teardown: { destroyAfterEach: false } + teardown: { destroyAfterEach: true } });