diff --git a/src/addons/mod/quiz/pages/player/player.page.ts b/src/addons/mod/quiz/pages/player/player.page.ts index 4eb7dd7ea..42b91c462 100644 --- a/src/addons/mod/quiz/pages/player/player.page.ts +++ b/src/addons/mod/quiz/pages/player/player.page.ts @@ -47,7 +47,7 @@ import { CanLeave } from '@guards/can-leave'; import { CoreForms } from '@singletons/form'; import { CoreDom } from '@singletons/dom'; import { CoreTime } from '@singletons/time'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; /** * Page that allows attempting a quiz. @@ -690,7 +690,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave { */ protected async scrollToQuestion(slot: number): Promise { await CoreUtils.nextTick(); - await CoreComponentsRegistry.waitComponentsReady(this.elementRef.nativeElement, 'core-question'); + await CoreDirectivesRegistry.waitDirectivesReady(this.elementRef.nativeElement, 'core-question'); await CoreDom.scrollToElement( this.elementRef.nativeElement, '#addon-mod_quiz-question-' + slot, diff --git a/src/addons/qtype/ddwtos/classes/ddwtos.ts b/src/addons/qtype/ddwtos/classes/ddwtos.ts index 152b38766..a06ac2928 100644 --- a/src/addons/qtype/ddwtos/classes/ddwtos.ts +++ b/src/addons/qtype/ddwtos/classes/ddwtos.ts @@ -15,7 +15,7 @@ import { CoreFormatTextDirective } from '@directives/format-text'; import { CoreTextUtils } from '@services/utils/text'; import { CoreUtils } from '@services/utils/utils'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreCoordinates, CoreDom } from '@singletons/dom'; import { CoreEventObserver } from '@singletons/events'; import { CoreLogger } from '@singletons/logger'; @@ -427,7 +427,7 @@ export class AddonQtypeDdwtosQuestion { protected async waitForReady(): Promise { await CoreDom.waitToBeInDOM(this.container); - await CoreComponentsRegistry.waitComponentsReady(this.container, 'core-format-text', CoreFormatTextDirective); + await CoreDirectivesRegistry.waitDirectivesReady(this.container, 'core-format-text', CoreFormatTextDirective); const drag = Array.from(this.container.querySelectorAll(this.selectors.dragHomes()))[0]; diff --git a/src/core/classes/async-component.ts b/src/core/classes/async-directive.ts similarity index 80% rename from src/core/classes/async-component.ts rename to src/core/classes/async-directive.ts index 77635a70f..b659dc253 100644 --- a/src/core/classes/async-component.ts +++ b/src/core/classes/async-directive.ts @@ -13,12 +13,12 @@ // limitations under the License. /** - * Component that is not rendered immediately after being mounted. + * Directive that is not rendered immediately after being mounted. */ -export interface AsyncComponent { +export interface AsyncDirective { /** - * Wait until the component is fully rendered and ready. + * Wait until the directive is fully rendered and ready. */ ready(): Promise; } diff --git a/src/core/classes/page-load-watcher.ts b/src/core/classes/page-load-watcher.ts index 52bba8de7..e062e3b98 100644 --- a/src/core/classes/page-load-watcher.ts +++ b/src/core/classes/page-load-watcher.ts @@ -15,7 +15,7 @@ import { CoreSitesReadingStrategy } from '@services/sites'; import { CoreUtils } from '@services/utils/utils'; import { Subscription } from 'rxjs'; -import { AsyncComponent } from './async-component'; +import { AsyncDirective } from './async-directive'; import { PageLoadsManager } from './page-loads-manager'; import { CorePromisedValue } from './promised-value'; import { WSObservable } from './site'; @@ -27,7 +27,7 @@ export class PageLoadWatcher { protected hasChanges = false; protected ongoingRequests = 0; - protected components = new Set(); + protected components = new Set(); protected loadedTimeout?: number; protected hasChangesPromises: Promise[] = []; @@ -66,7 +66,7 @@ export class PageLoadWatcher { * * @param component Component instance. */ - async watchComponent(component: AsyncComponent): Promise { + async watchComponent(component: AsyncDirective): Promise { this.components.add(component); clearTimeout(this.loadedTimeout); diff --git a/src/core/classes/page-loads-manager.ts b/src/core/classes/page-loads-manager.ts index 24a28c4a1..c3c179ec0 100644 --- a/src/core/classes/page-loads-manager.ts +++ b/src/core/classes/page-loads-manager.ts @@ -16,7 +16,7 @@ import { CoreRefreshButtonModalComponent } from '@components/refresh-button-moda import { CoreNavigator } from '@services/navigator'; import { CoreDomUtils } from '@services/utils/dom'; import { Subject } from 'rxjs'; -import { AsyncComponent } from './async-component'; +import { AsyncDirective } from './async-directive'; import { PageLoadWatcher } from './page-load-watcher'; /** @@ -37,7 +37,7 @@ export class PageLoadsManager { * @param staleWhileRevalidate Whether to use stale while revalidate strategy. * @returns Load watcher to use. */ - startPageLoad(page: AsyncComponent, staleWhileRevalidate: boolean): PageLoadWatcher { + startPageLoad(page: AsyncDirective, staleWhileRevalidate: boolean): PageLoadWatcher { this.initialPath = this.initialPath ?? CoreNavigator.getCurrentPath(); this.currentLoadWatcher = new PageLoadWatcher(this, staleWhileRevalidate); this.ongoingLoadWatchers.add(this.currentLoadWatcher); @@ -53,7 +53,7 @@ export class PageLoadsManager { * @param component Component instance. * @returns Load watcher to use. */ - startComponentLoad(component: AsyncComponent): PageLoadWatcher { + startComponentLoad(component: AsyncDirective): PageLoadWatcher { // If a component is loading data without the page loading data, probably the component is reloading/refreshing. // In that case, create a load watcher instance but don't store it in currentLoadWatcher because it's not a page load. const loadWatcher = this.currentLoadWatcher ?? new PageLoadWatcher(this, false); diff --git a/src/core/classes/tabs.ts b/src/core/classes/tabs.ts index 5fe244c3a..f74babe68 100644 --- a/src/core/classes/tabs.ts +++ b/src/core/classes/tabs.ts @@ -37,8 +37,8 @@ import { CoreDom } from '@singletons/dom'; import { CoreUtils } from '@services/utils/utils'; import { CoreError } from './errors/error'; import { CorePromisedValue } from './promised-value'; -import { AsyncComponent } from './async-component'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { AsyncDirective } from './async-directive'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CorePlatform } from '@services/platform'; /** @@ -47,7 +47,7 @@ import { CorePlatform } from '@services/platform'; @Component({ template: '', }) -export class CoreTabsBaseComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy, AsyncComponent { +export class CoreTabsBaseComponent implements OnInit, AfterViewInit, OnChanges, OnDestroy, AsyncDirective { // Minimum tab's width. protected static readonly MIN_TAB_WIDTH = 107; @@ -99,7 +99,7 @@ export class CoreTabsBaseComponent implements OnInit, Aft this.tabAction = new CoreTabsRoleTab(this); - CoreComponentsRegistry.register(element.nativeElement, this); + CoreDirectivesRegistry.register(element.nativeElement, this); } /** diff --git a/src/core/components/context-menu/context-menu.ts b/src/core/components/context-menu/context-menu.ts index 157407562..33710b712 100644 --- a/src/core/components/context-menu/context-menu.ts +++ b/src/core/components/context-menu/context-menu.ts @@ -20,7 +20,7 @@ import { CoreUtils } from '@services/utils/utils'; import { Translate } from '@singletons'; import { CoreContextMenuItemComponent } from './context-menu-item'; import { CoreContextMenuPopoverComponent } from './context-menu-popover'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; /** * This component adds a button (usually in the navigation bar) that displays a context menu popover. @@ -61,7 +61,7 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy { // Calculate the unique ID. this.uniqueId = 'core-context-menu-' + CoreUtils.getUniqueId('CoreContextMenuComponent'); - CoreComponentsRegistry.register(elementRef.nativeElement, this); + CoreDirectivesRegistry.register(elementRef.nativeElement, this); } /** diff --git a/src/core/components/loading/loading.ts b/src/core/components/loading/loading.ts index 6db45e3c8..832853f95 100644 --- a/src/core/components/loading/loading.ts +++ b/src/core/components/loading/loading.ts @@ -18,9 +18,9 @@ import { CoreEventLoadingChangedData, CoreEvents } from '@singletons/events'; import { CoreUtils } from '@services/utils/utils'; import { CoreAnimations } from '@components/animations'; import { Translate } from '@singletons'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CorePromisedValue } from '@classes/promised-value'; -import { AsyncComponent } from '@classes/async-component'; +import { AsyncDirective } from '@classes/async-directive'; import { CoreApp } from '@services/app'; /** @@ -49,7 +49,7 @@ import { CoreApp } from '@services/app'; styleUrls: ['loading.scss'], animations: [CoreAnimations.SHOW_HIDE], }) -export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, AsyncComponent, OnDestroy { +export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, AsyncDirective, OnDestroy { @Input() hideUntil: unknown = false; // Determine when should the contents be shown. @Input() message?: string; // Message to show while loading. @@ -65,7 +65,7 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, A constructor(element: ElementRef) { this.element = element.nativeElement; - CoreComponentsRegistry.register(this.element, this); + CoreDirectivesRegistry.register(this.element, this); // Calculate the unique ID. this.uniqueId = 'core-loading-content-' + CoreUtils.getUniqueId('CoreLoadingComponent'); diff --git a/src/core/components/navbar-buttons/navbar-buttons.ts b/src/core/components/navbar-buttons/navbar-buttons.ts index 83e18fb47..3cceba4bb 100644 --- a/src/core/components/navbar-buttons/navbar-buttons.ts +++ b/src/core/components/navbar-buttons/navbar-buttons.ts @@ -25,7 +25,7 @@ import { import { CoreLogger } from '@singletons/logger'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreContextMenuComponent } from '../context-menu/context-menu'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDom } from '@singletons/dom'; const BUTTON_HIDDEN_CLASS = 'core-navbar-button-hidden'; @@ -82,7 +82,7 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy { this.element = element.nativeElement; this.logger = CoreLogger.getInstance('CoreNavBarButtonsComponent'); - CoreComponentsRegistry.register(this.element, this); + CoreDirectivesRegistry.register(this.element, this); } /** @@ -156,11 +156,11 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy { } const mainContextMenu = buttonsContainer.querySelector('core-context-menu'); - const secondaryContextMenuInstance = CoreComponentsRegistry.resolve(secondaryContextMenu, CoreContextMenuComponent); + const secondaryContextMenuInstance = CoreDirectivesRegistry.resolve(secondaryContextMenu, CoreContextMenuComponent); let mainContextMenuInstance: CoreContextMenuComponent | null; if (mainContextMenu) { // Both containers have a context menu. Merge them to prevent having 2 menus at the same time. - mainContextMenuInstance = CoreComponentsRegistry.resolve(mainContextMenu, CoreContextMenuComponent); + mainContextMenuInstance = CoreDirectivesRegistry.resolve(mainContextMenu, CoreContextMenuComponent); } else { // There is a context-menu in these buttons, but there is no main context menu in the header. // Create one main context menu dynamically. diff --git a/src/core/components/tabs-outlet/tabs-outlet.ts b/src/core/components/tabs-outlet/tabs-outlet.ts index 93d72b195..81f56cb08 100644 --- a/src/core/components/tabs-outlet/tabs-outlet.ts +++ b/src/core/components/tabs-outlet/tabs-outlet.ts @@ -31,7 +31,7 @@ import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons'; import { StackEvent } from '@ionic/angular/directives/navigation/stack-utils'; import { CoreNavigator } from '@services/navigator'; import { CoreTabBase, CoreTabsBaseComponent } from '@classes/tabs'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; /** * This component displays some top scrollable tabs that will autohide on vertical scroll. @@ -207,7 +207,7 @@ export class CoreTabsOutletComponent extends CoreTabsBaseComponent { - const instance = CoreComponentsRegistry.resolve(element, CoreNavBarButtonsComponent); + const instance = CoreDirectivesRegistry.resolve(element, CoreNavBarButtonsComponent); if (instance) { const pagetagName = element.closest('.ion-page')?.tagName; diff --git a/src/core/components/tabs/tab.ts b/src/core/components/tabs/tab.ts index 3d9e40561..a93de6abc 100644 --- a/src/core/components/tabs/tab.ts +++ b/src/core/components/tabs/tab.ts @@ -16,7 +16,7 @@ import { Component, Input, Output, OnInit, OnDestroy, ElementRef, EventEmitter, import { CoreTabBase } from '@classes/tabs'; import { CoreUtils } from '@services/utils/utils'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons'; import { CoreTabsComponent } from './tabs'; @@ -140,7 +140,7 @@ export class CoreTabComponent implements OnInit, OnDestroy, CoreTabBase { protected showHideNavBarButtons(show: boolean): void { const elements = this.element.querySelectorAll('core-navbar-buttons'); elements.forEach((element) => { - const instance = CoreComponentsRegistry.resolve(element, CoreNavBarButtonsComponent); + const instance = CoreDirectivesRegistry.resolve(element, CoreNavBarButtonsComponent); if (instance) { instance.forceHide(!show); diff --git a/src/core/directives/collapsible-footer.ts b/src/core/directives/collapsible-footer.ts index e93fab948..de58fcedb 100644 --- a/src/core/directives/collapsible-footer.ts +++ b/src/core/directives/collapsible-footer.ts @@ -17,7 +17,7 @@ import { ScrollDetail } from '@ionic/core'; import { IonContent } from '@ionic/angular'; import { CoreUtils } from '@services/utils/utils'; import { CoreMath } from '@singletons/math'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreFormatTextDirective } from './format-text'; import { CoreEventObserver } from '@singletons/events'; import { CoreLoadingComponent } from '@components/loading/loading'; @@ -203,7 +203,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { * Wait until all children inside the element are done rendering. */ protected async waitFormatTextsRendered(): Promise { - await CoreComponentsRegistry.waitComponentsReady(this.element, 'core-format-text', CoreFormatTextDirective); + await CoreDirectivesRegistry.waitDirectivesReady(this.element, 'core-format-text', CoreFormatTextDirective); } /** @@ -249,8 +249,8 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { const scrollElement = await this.ionContent.getScrollElement(); await Promise.all([ - await CoreComponentsRegistry.waitComponentsReady(scrollElement, 'core-loading', CoreLoadingComponent), - await CoreComponentsRegistry.waitComponentsReady(this.element, 'core-loading', CoreLoadingComponent), + await CoreDirectivesRegistry.waitDirectivesReady(scrollElement, 'core-loading', CoreLoadingComponent), + await CoreDirectivesRegistry.waitDirectivesReady(this.element, 'core-loading', CoreLoadingComponent), ]); } diff --git a/src/core/directives/collapsible-header.ts b/src/core/directives/collapsible-header.ts index fbd6ff845..28d1c7f09 100644 --- a/src/core/directives/collapsible-header.ts +++ b/src/core/directives/collapsible-header.ts @@ -21,7 +21,7 @@ import { CoreTabsComponent } from '@components/tabs/tabs'; import { CoreSettingsHelper } from '@features/settings/services/settings-helper'; import { ScrollDetail } from '@ionic/core'; import { CoreUtils } from '@services/utils/utils'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDom } from '@singletons/dom'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreMath } from '@singletons/math'; @@ -294,7 +294,7 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest this.listenEvents(); // Initialize from tabs. - const tabs = CoreComponentsRegistry.resolve(this.page.querySelector('core-tabs-outlet'), CoreTabsOutletComponent); + const tabs = CoreDirectivesRegistry.resolve(this.page.querySelector('core-tabs-outlet'), CoreTabsOutletComponent); if (tabs) { const outlet = tabs.getOutlet(); @@ -424,14 +424,14 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest } // Wait loadings to finish. - await CoreComponentsRegistry.waitComponentsReady(this.page, 'core-loading', CoreLoadingComponent); + await CoreDirectivesRegistry.waitDirectivesReady(this.page, 'core-loading', CoreLoadingComponent); // Wait tabs to be ready. - await CoreComponentsRegistry.waitComponentsReady(this.page, 'core-tabs', CoreTabsComponent); - await CoreComponentsRegistry.waitComponentsReady(this.page, 'core-tabs-outlet', CoreTabsOutletComponent); + await CoreDirectivesRegistry.waitDirectivesReady(this.page, 'core-tabs', CoreTabsComponent); + await CoreDirectivesRegistry.waitDirectivesReady(this.page, 'core-tabs-outlet', CoreTabsOutletComponent); // Wait loadings to finish, inside tabs (if any). - await CoreComponentsRegistry.waitComponentsReady( + await CoreDirectivesRegistry.waitDirectivesReady( this.page, 'core-tab core-loading, ion-router-outlet core-loading', CoreLoadingComponent, @@ -445,7 +445,7 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest * @returns Promise resolved when texts are rendered. */ protected async waitFormatTextsRendered(element: Element): Promise { - await CoreComponentsRegistry.waitComponentsReady(element, 'core-format-text', CoreFormatTextDirective); + await CoreDirectivesRegistry.waitDirectivesReady(element, 'core-format-text', CoreFormatTextDirective); } /** diff --git a/src/core/directives/collapsible-item.ts b/src/core/directives/collapsible-item.ts index 635da33e6..a845e0a14 100644 --- a/src/core/directives/collapsible-item.ts +++ b/src/core/directives/collapsible-item.ts @@ -19,7 +19,7 @@ import { CoreSettingsHelper } from '@features/settings/services/settings-helper' import { CoreUtils } from '@services/utils/utils'; import { Translate } from '@singletons'; import { CoreColors } from '@singletons/colors'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDom } from '@singletons/dom'; import { CoreEventObserver } from '@singletons/events'; import { Subscription } from 'rxjs'; @@ -128,14 +128,14 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy { return; } - await CoreComponentsRegistry.waitComponentsReady(this.page, 'core-loading', CoreLoadingComponent); + await CoreDirectivesRegistry.waitDirectivesReady(this.page, 'core-loading', CoreLoadingComponent); } /** * Wait until all children inside the element are done rendering. */ protected async waitFormatTextsRendered(): Promise { - await CoreComponentsRegistry.waitComponentsReady(this.element, 'core-format-text', CoreFormatTextDirective); + await CoreDirectivesRegistry.waitDirectivesReady(this.element, 'core-format-text', CoreFormatTextDirective); } /** diff --git a/src/core/directives/format-text.ts b/src/core/directives/format-text.ts index 05e911330..4b6be6171 100644 --- a/src/core/directives/format-text.ts +++ b/src/core/directives/format-text.ts @@ -42,10 +42,10 @@ import { CoreFilter, CoreFilterFilter, CoreFilterFormatTextOptions } from '@feat import { CoreFilterDelegate } from '@features/filter/services/filter-delegate'; import { CoreFilterHelper } from '@features/filter/services/filter-helper'; import { CoreSubscriptions } from '@singletons/subscriptions'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreCollapsibleItemDirective } from './collapsible-item'; import { CoreCancellablePromise } from '@classes/cancellable-promise'; -import { AsyncComponent } from '@classes/async-component'; +import { AsyncDirective } from '@classes/async-directive'; import { CorePath } from '@singletons/path'; import { CoreDom } from '@singletons/dom'; import { CoreEvents } from '@singletons/events'; @@ -67,7 +67,7 @@ import { FrameElementController } from '@classes/element-controllers/FrameElemen @Directive({ selector: 'core-format-text', }) -export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncComponent { +export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncDirective { @ViewChild(CoreCollapsibleItemDirective) collapsible?: CoreCollapsibleItemDirective; @@ -111,7 +111,7 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncCompo protected viewContainerRef: ViewContainerRef, @Optional() @Inject(CORE_REFRESH_CONTEXT) protected refreshContext?: CoreRefreshContext, ) { - CoreComponentsRegistry.register(element.nativeElement, this); + CoreDirectivesRegistry.register(element.nativeElement, this); this.element = element.nativeElement; this.element.classList.add('core-loading'); // Hide contents until they're treated. diff --git a/src/core/features/block/classes/base-block-component.ts b/src/core/features/block/classes/base-block-component.ts index 368519223..c6073cac6 100644 --- a/src/core/features/block/classes/base-block-component.ts +++ b/src/core/features/block/classes/base-block-component.ts @@ -21,7 +21,7 @@ import { CoreCourseBlock } from '../../course/services/course'; import { Params } from '@angular/router'; import { ContextLevel } from '@/core/constants'; import { CoreNavigationOptions } from '@services/navigator'; -import { AsyncComponent } from '@classes/async-component'; +import { AsyncDirective } from '@classes/async-directive'; import { CorePromisedValue } from '@classes/promised-value'; /** @@ -30,7 +30,7 @@ import { CorePromisedValue } from '@classes/promised-value'; @Component({ template: '', }) -export abstract class CoreBlockBaseComponent implements OnInit, ICoreBlockComponent, AsyncComponent { +export abstract class CoreBlockBaseComponent implements OnInit, ICoreBlockComponent, AsyncDirective { @Input() title!: string; // The block title. @Input() block!: CoreCourseBlock; // The block to render. diff --git a/src/core/features/compile/services/compile.ts b/src/core/features/compile/services/compile.ts index 51fdcea13..0ba9a739c 100644 --- a/src/core/features/compile/services/compile.ts +++ b/src/core/features/compile/services/compile.ts @@ -79,6 +79,7 @@ import { Md5 } from 'ts-md5/dist/md5'; import { CoreSyncBaseProvider } from '@classes/base-sync'; import { CoreArray } from '@singletons/array'; import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDom } from '@singletons/dom'; import { CoreForms } from '@singletons/form'; import { CoreText } from '@singletons/text'; @@ -350,6 +351,7 @@ export class CoreCompileProvider { instance['CoreSyncBaseProvider'] = CoreSyncBaseProvider; instance['CoreArray'] = CoreArray; instance['CoreComponentsRegistry'] = CoreComponentsRegistry; + instance['CoreDirectivesRegistry'] = CoreDirectivesRegistry; instance['CoreNetwork'] = CoreNetwork.instance; instance['CorePlatform'] = CorePlatform.instance; instance['CoreDom'] = CoreDom; diff --git a/src/core/features/courses/pages/my/my.ts b/src/core/features/courses/pages/my/my.ts index ef5ae03a4..3a8e8c2b8 100644 --- a/src/core/features/courses/pages/my/my.ts +++ b/src/core/features/courses/pages/my/my.ts @@ -14,7 +14,7 @@ import { AddonBlockMyOverviewComponent } from '@addons/block/myoverview/components/myoverview/myoverview'; import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; -import { AsyncComponent } from '@classes/async-component'; +import { AsyncDirective } from '@classes/async-directive'; import { PageLoadsManager } from '@classes/page-loads-manager'; import { CorePromisedValue } from '@classes/promised-value'; import { CoreBlockComponent } from '@features/block/components/block/block'; @@ -42,7 +42,7 @@ import { CoreCourses } from '../../services/courses'; useClass: PageLoadsManager, }], }) -export class CoreCoursesMyCoursesPage implements OnInit, OnDestroy, AsyncComponent { +export class CoreCoursesMyCoursesPage implements OnInit, OnDestroy, AsyncDirective { @ViewChild(CoreBlockComponent) block!: CoreBlockComponent; diff --git a/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts b/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts index 6b0e660c3..5b32415bb 100644 --- a/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts +++ b/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts @@ -36,7 +36,7 @@ import { CoreUtils } from '@services/utils/utils'; import { Translate } from '@singletons'; import { CoreEventFormActionData, CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreEditorOffline } from '../../services/editor-offline'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreLoadingComponent } from '@components/loading/loading'; import { CoreScreen } from '@services/screen'; import { CoreCancellablePromise } from '@classes/cancellable-promise'; @@ -304,7 +304,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterViewInit, return; } - await CoreComponentsRegistry.waitComponentsReady(page, 'core-loading', CoreLoadingComponent); + await CoreDirectivesRegistry.waitDirectivesReady(page, 'core-loading', CoreLoadingComponent); } /** diff --git a/src/core/features/question/components/question/question.ts b/src/core/features/question/components/question/question.ts index af9c2d08e..9d6d349ef 100644 --- a/src/core/features/question/components/question/question.ts +++ b/src/core/features/question/components/question/question.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Component, Input, Output, OnInit, EventEmitter, ChangeDetectorRef, Type, ElementRef } from '@angular/core'; -import { AsyncComponent } from '@classes/async-component'; +import { AsyncDirective } from '@classes/async-directive'; import { CorePromisedValue } from '@classes/promised-value'; import { CoreQuestionBehaviourDelegate } from '@features/question/services/behaviour-delegate'; import { CoreQuestionDelegate } from '@features/question/services/question-delegate'; @@ -22,7 +22,7 @@ import { CoreQuestionBehaviourButton, CoreQuestionHelper, CoreQuestionQuestion } import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { Translate } from '@singletons'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreLogger } from '@singletons/logger'; /** @@ -33,7 +33,7 @@ import { CoreLogger } from '@singletons/logger'; templateUrl: 'core-question.html', styleUrls: ['../../question.scss'], }) -export class CoreQuestionComponent implements OnInit, AsyncComponent { +export class CoreQuestionComponent implements OnInit, AsyncDirective { @Input() question?: CoreQuestionQuestion; // The question to render. @Input() component?: string; // The component the question belongs to. @@ -66,7 +66,7 @@ export class CoreQuestionComponent implements OnInit, AsyncComponent { constructor(protected changeDetector: ChangeDetectorRef, private element: ElementRef) { this.logger = CoreLogger.getInstance('CoreQuestionComponent'); this.promisedReady = new CorePromisedValue(); - CoreComponentsRegistry.register(this.element.nativeElement, this); + CoreDirectivesRegistry.register(this.element.nativeElement, this); } async ready(): Promise { diff --git a/src/core/features/usertours/components/user-tour/user-tour.ts b/src/core/features/usertours/components/user-tour/user-tour.ts index 5fcb9c2eb..2f278d8fc 100644 --- a/src/core/features/usertours/components/user-tour/user-tour.ts +++ b/src/core/features/usertours/components/user-tour/user-tour.ts @@ -30,7 +30,7 @@ import { CoreUserToursPopoverLayout } from '@features/usertours/classes/popover- import { CoreUserTours, CoreUserToursAlignment, CoreUserToursSide } from '@features/usertours/services/user-tours'; import { CoreDomUtils } from '@services/utils/dom'; import { AngularFrameworkDelegate } from '@singletons'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDom } from '@singletons/dom'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreMainMenuProvider } from '@features/mainmenu/services/mainmenu'; @@ -84,7 +84,7 @@ export class CoreUserToursUserTourComponent implements AfterViewInit, OnDestroy constructor({ nativeElement: element }: ElementRef) { this.element = element; - CoreComponentsRegistry.register(element, this); + CoreDirectivesRegistry.register(element, this); this.element.addEventListener('click', (event) => this.dismissOnBackOrBackdrop(event.target as HTMLElement)); diff --git a/src/core/features/usertours/services/user-tours.ts b/src/core/features/usertours/services/user-tours.ts index 2c3712d31..a79b60f93 100644 --- a/src/core/features/usertours/services/user-tours.ts +++ b/src/core/features/usertours/services/user-tours.ts @@ -21,7 +21,7 @@ import { CoreDatabaseCachingStrategy, CoreDatabaseTableProxy } from '@classes/da import { CoreApp } from '@services/app'; import { CoreUtils } from '@services/utils/utils'; import { AngularFrameworkDelegate, makeSingleton } from '@singletons'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDom } from '@singletons/dom'; import { CoreSubscriptions } from '@singletons/subscriptions'; import { CoreUserToursUserTourComponent } from '../components/user-tour/user-tour'; @@ -120,7 +120,7 @@ export class CoreUserToursService { CoreUserToursUserTourComponent, { ...componentOptions, container }, ); - const tour = CoreComponentsRegistry.require(element, CoreUserToursUserTourComponent); + const tour = CoreDirectivesRegistry.require(element, CoreUserToursUserTourComponent); return this.startTour(tour, options.watch ?? (options as CoreUserToursFocusedOptions).focus); } diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts index bca8e0701..33dad4c11 100644 --- a/src/core/services/utils/dom.ts +++ b/src/core/services/utils/dom.ts @@ -51,7 +51,7 @@ import { CoreSites } from '@services/sites'; import { NavigationStart } from '@angular/router'; import { filter } from 'rxjs/operators'; import { Subscription } from 'rxjs'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDom } from '@singletons/dom'; import { CoreNetwork } from '@services/network'; import { CoreSiteError } from '@classes/errors/siteerror'; @@ -665,10 +665,10 @@ export class CoreDomUtilsProvider { * * @param element The root element of the component/directive. * @returns The instance, undefined if not found. - * @deprecated since 4.0.0. Use CoreComponentsRegistry instead. + * @deprecated since 4.0.0. Use CoreDirectivesRegistry instead. */ getInstanceByElement(element: Element): T | undefined { - return CoreComponentsRegistry.resolve(element) ?? undefined; + return CoreDirectivesRegistry.resolve(element) ?? undefined; } /** @@ -1718,10 +1718,10 @@ export class CoreDomUtilsProvider { * * @param element The root element of the component/directive. * @param instance The instance to store. - * @deprecated since 4.0.0. Use CoreComponentsRegistry instead. + * @deprecated since 4.0.0. Use CoreDirectivesRegistry instead. */ storeInstanceByElement(element: Element, instance: unknown): void { - CoreComponentsRegistry.register(element, instance); + CoreDirectivesRegistry.register(element, instance); } /** diff --git a/src/core/singletons/components-registry.ts b/src/core/singletons/components-registry.ts index d79e9ca9e..cd123802f 100644 --- a/src/core/singletons/components-registry.ts +++ b/src/core/singletons/components-registry.ts @@ -13,12 +13,14 @@ // limitations under the License. import { Component } from '@angular/core'; -import { AsyncComponent } from '@classes/async-component'; +import { AsyncDirective } from '@classes/async-directive'; import { CoreUtils } from '@services/utils/utils'; import { CoreLogger } from './logger'; /** * Registry to keep track of component instances. + * + * @deprecated since 4.1.1. Use CoreDirectivesRegistry instead. */ export class CoreComponentsRegistry { @@ -74,7 +76,7 @@ export class CoreComponentsRegistry { * @param componentClass Component class. * @returns Promise resolved when done. */ - static async waitComponentReady( + static async waitComponentReady( element: Element | null, componentClass?: ComponentConstructor, ): Promise { @@ -96,7 +98,7 @@ export class CoreComponentsRegistry { * @param componentClass Component class. * @returns Promise resolved when done. */ - static async waitComponentsReady( + static async waitComponentsReady( element: Element, selector: string, componentClass?: ComponentConstructor, diff --git a/src/core/singletons/directives-registry.ts b/src/core/singletons/directives-registry.ts new file mode 100644 index 000000000..a1b17e5b1 --- /dev/null +++ b/src/core/singletons/directives-registry.ts @@ -0,0 +1,145 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// 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 { Directive } from '@angular/core'; +import { AsyncDirective } from '@classes/async-directive'; +import { CoreUtils } from '@services/utils/utils'; +import { CoreLogger } from './logger'; + +/** + * Registry to keep track of directive instances. + */ +export class CoreDirectivesRegistry { + + private static instances: WeakMap = new WeakMap(); + protected static logger = CoreLogger.getInstance('CoreDirectivesRegistry'); + + /** + * Register a directive instance. + * + * @param element Root element. + * @param instance Directive instance. + */ + static register(element: Element, instance: unknown): void { + const list = this.instances.get(element) ?? []; + list.push(instance); + this.instances.set(element, list); + } + + /** + * Resolve a directive instance. + * + * @param element Root element. + * @param directiveClass Directive class. + * @returns Directive instance. + */ + static resolve(element?: Element | null, directiveClass?: DirectiveConstructor): T | null { + const list = (element && this.instances.get(element) as T[]) ?? []; + + return list.find(instance => !directiveClass || instance instanceof directiveClass) ?? null; + } + + /** + * Resolve all directive instances. + * + * @param element Root element. + * @param directiveClass Directive class. + * @returns Directive instances. + */ + static resolveAll(element?: Element | null, directiveClass?: DirectiveConstructor): T[] { + const list = (element && this.instances.get(element) as T[]) ?? []; + + return list.filter(instance => !directiveClass || instance instanceof directiveClass) ?? []; + } + + /** + * Get a directive instance and fail if it cannot be resolved. + * + * @param element Root element. + * @param directiveClass Directive class. + * @returns Directive instance. + */ + static require(element: Element, directiveClass?: DirectiveConstructor): T { + const instance = this.resolve(element, directiveClass); + + if (!instance) { + throw new Error('Couldn\'t resolve directive instance'); + } + + return instance; + } + + /** + * Get a directive instance and wait to be ready. + * + * @param element Root element. + * @param directiveClass Directive class. + * @returns Promise resolved when done. + */ + static async waitDirectiveReady( + element: Element | null, + directiveClass?: DirectiveConstructor, + ): Promise { + const instance = this.resolve(element, directiveClass); + if (!instance) { + this.logger.error('No instance registered for element ' + directiveClass, element); + + return; + } + + await instance.ready(); + } + + /** + * Get all directive instances and wait to be ready. + * + * @param element Root element. + * @param directiveClass Directive class. + * @returns Promise resolved when done. + */ + static async waitDirectivesReady( + element: Element, + selector?: string, + directiveClass?: DirectiveConstructor, + ): Promise { + let elements: Element[] = []; + + if (!selector || element.matches(selector)) { + // Element to wait is myself. + elements = [element]; + } else { + elements = Array.from(element.querySelectorAll(selector)); + } + + if (!elements.length) { + return; + } + + await Promise.all(elements.map(async element => { + const instances = this.resolveAll(element, directiveClass); + + await Promise.all(instances.map(instance => instance.ready())); + })); + + // Wait for next tick to ensure directives are completely rendered. + await CoreUtils.nextTick(); + } + +} + +/** + * Directive constructor. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type DirectiveConstructor = { new(...args: any[]): T }; diff --git a/src/core/singletons/events.ts b/src/core/singletons/events.ts index fb1a9c33a..4f33ad1fa 100644 --- a/src/core/singletons/events.ts +++ b/src/core/singletons/events.ts @@ -108,7 +108,7 @@ export class CoreEvents { static readonly FILE_SHARED = 'file_shared'; static readonly KEYBOARD_CHANGE = 'keyboard_change'; /** - * @deprecated since app 4.0. Use CoreComponentsRegistry promises instead. + * @deprecated since app 4.0. Use CoreDirectivesRegistry promises instead. */ static readonly CORE_LOADING_CHANGED = 'core_loading_changed'; static readonly ORIENTATION_CHANGE = 'orientation_change'; diff --git a/src/core/singletons/tests/components-registry.test.ts b/src/core/singletons/tests/components-registry.test.ts deleted file mode 100644 index 4cdeb231a..000000000 --- a/src/core/singletons/tests/components-registry.test.ts +++ /dev/null @@ -1,104 +0,0 @@ -// (C) Copyright 2015 Moodle Pty Ltd. -// -// 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 { wait } from '@/testing/utils'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; - -const cssClassName = 'core-components-registry-test'; -const createAndRegisterInstance = () => { - const element = document.createElement('div'); - element.classList.add(cssClassName); - const instance = new ComponentsRegistryTestClass(); - - CoreComponentsRegistry.register(element, instance); - - return { element, instance }; -}; - -describe('CoreComponentsRegistry singleton', () => { - - let element: HTMLElement; - let testClassInstance: ComponentsRegistryTestClass; - - beforeEach(() => { - const result = createAndRegisterInstance(); - element = result.element; - testClassInstance = result.instance; - }); - - it('resolves stored instances', () => { - expect(CoreComponentsRegistry.resolve(element)).toEqual(testClassInstance); - expect(CoreComponentsRegistry.resolve(element, ComponentsRegistryTestClass)).toEqual(testClassInstance); - expect(CoreComponentsRegistry.resolve(element, CoreComponentsRegistry)).toEqual(null); - expect(CoreComponentsRegistry.resolve(document.createElement('div'))).toEqual(null); - }); - - it('requires stored instances', () => { - expect(CoreComponentsRegistry.require(element)).toEqual(testClassInstance); - expect(CoreComponentsRegistry.require(element, ComponentsRegistryTestClass)).toEqual(testClassInstance); - expect(() => CoreComponentsRegistry.require(element, CoreComponentsRegistry)).toThrow(); - expect(() => CoreComponentsRegistry.require(document.createElement('div'))).toThrow(); - }); - - it('waits for component ready', async () => { - expect(testClassInstance.isReady).toBe(false); - - await CoreComponentsRegistry.waitComponentReady(element); - - expect(testClassInstance.isReady).toBe(true); - }); - - it('waits for components ready: just one', async () => { - expect(testClassInstance.isReady).toBe(false); - - await CoreComponentsRegistry.waitComponentsReady(element, `.${cssClassName}`); - - expect(testClassInstance.isReady).toBe(true); - }); - - it('waits for components ready: multiple', async () => { - const secondResult = createAndRegisterInstance(); - const thirdResult = createAndRegisterInstance(); - thirdResult.element.classList.remove(cssClassName); // Remove the class so the element and instance aren't treated. - - const parent = document.createElement('div'); - parent.appendChild(element); - parent.appendChild(secondResult.element); - parent.appendChild(thirdResult.element); - - expect(testClassInstance.isReady).toBe(false); - expect(secondResult.instance.isReady).toBe(false); - expect(thirdResult.instance.isReady).toBe(false); - - await CoreComponentsRegistry.waitComponentsReady(parent, `.${cssClassName}`); - - expect(testClassInstance.isReady).toBe(true); - expect(secondResult.instance.isReady).toBe(true); - expect(thirdResult.instance.isReady).toBe(false); - }); - -}); - -class ComponentsRegistryTestClass { - - randomId = Math.random(); - isReady = false; - - async ready(): Promise { - await wait(50); - - this.isReady = true; - } - -} diff --git a/src/core/singletons/tests/directives-registry.test.ts b/src/core/singletons/tests/directives-registry.test.ts new file mode 100644 index 000000000..c0cbdb825 --- /dev/null +++ b/src/core/singletons/tests/directives-registry.test.ts @@ -0,0 +1,169 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// 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 { wait } from '@/testing/utils'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; + +const cssClassName = 'core-directives-registry-test'; +const createAndRegisterInstance = (element?: HTMLElement) => { + element = element ?? document.createElement('div'); + element.classList.add(cssClassName); + const instance = new DirectivesRegistryTestClass(); + + CoreDirectivesRegistry.register(element, instance); + + return { element, instance }; +}; + +describe('CoreDirectivesRegistry singleton', () => { + + let element: HTMLElement; + let testClassInstance: DirectivesRegistryTestClass; + let testClassSecondInstance: DirectivesRegistryTestClass; + let testAltClassInstance: DirectivesRegistryAltTestClass; + + beforeEach(() => { + let result = createAndRegisterInstance(); + element = result.element; + testClassInstance = result.instance; + + result = createAndRegisterInstance(element); + testClassSecondInstance = result.instance; + + testAltClassInstance = new DirectivesRegistryAltTestClass(); + CoreDirectivesRegistry.register(element, testAltClassInstance); + }); + + it('resolves a stored instance', () => { + expect(CoreDirectivesRegistry.resolve(element)).toEqual(testClassInstance); + expect(CoreDirectivesRegistry.resolve(element, DirectivesRegistryTestClass)).toEqual(testClassInstance); + expect(CoreDirectivesRegistry.resolve(element, DirectivesRegistryAltTestClass)).toEqual(testAltClassInstance); + expect(CoreDirectivesRegistry.resolve(element, CoreDirectivesRegistry)).toEqual(null); + expect(CoreDirectivesRegistry.resolve(document.createElement('div'))).toEqual(null); + }); + + it('resolves all stored instances', () => { + expect(CoreDirectivesRegistry.resolveAll(element)).toEqual( + [testClassInstance, testClassSecondInstance, testAltClassInstance], + ); + expect(CoreDirectivesRegistry.resolveAll(element, DirectivesRegistryTestClass)).toEqual( + [testClassInstance, testClassSecondInstance], + ); + expect(CoreDirectivesRegistry.resolveAll(element, DirectivesRegistryAltTestClass)).toEqual([testAltClassInstance]); + expect(CoreDirectivesRegistry.resolveAll(element, CoreDirectivesRegistry)).toEqual([]); + expect(CoreDirectivesRegistry.resolveAll(document.createElement('div'))).toEqual([]); + }); + + it('requires a stored instance', () => { + expect(CoreDirectivesRegistry.require(element)).toEqual(testClassInstance); + expect(CoreDirectivesRegistry.require(element, DirectivesRegistryTestClass)).toEqual(testClassInstance); + expect(CoreDirectivesRegistry.require(element, DirectivesRegistryAltTestClass)).toEqual(testAltClassInstance); + expect(() => CoreDirectivesRegistry.require(element, CoreDirectivesRegistry)).toThrow(); + expect(() => CoreDirectivesRegistry.require(document.createElement('div'))).toThrow(); + }); + + it('waits for directive ready', async () => { + expect(testClassInstance.isReady).toBe(false); + + await CoreDirectivesRegistry.waitDirectiveReady(element); + + expect(testClassInstance.isReady).toBe(true); + }); + + it('waits for directives ready: just one element and directive', async () => { + const result = createAndRegisterInstance(); + expect(result.instance.isReady).toBe(false); + + await CoreDirectivesRegistry.waitDirectivesReady(result.element, `.${cssClassName}`); + + expect(result.instance.isReady).toBe(true); + expect(testClassInstance.isReady).toBe(false); + }); + + it('waits for directives ready: all directives, single element', async () => { + expect(testClassInstance.isReady).toBe(false); + expect(testClassSecondInstance.isReady).toBe(false); + expect(testAltClassInstance.isReady).toBe(false); + + await CoreDirectivesRegistry.waitDirectivesReady(element); + + expect(testClassInstance.isReady).toBe(true); + expect(testClassSecondInstance.isReady).toBe(true); + expect(testAltClassInstance.isReady).toBe(true); + }); + + it('waits for directives ready: filter by class, single element', async () => { + expect(testClassInstance.isReady).toBe(false); + expect(testClassSecondInstance.isReady).toBe(false); + expect(testAltClassInstance.isReady).toBe(false); + + await CoreDirectivesRegistry.waitDirectivesReady(element, `.${cssClassName}`, DirectivesRegistryTestClass); + + expect(testClassInstance.isReady).toBe(true); + expect(testClassSecondInstance.isReady).toBe(true); + expect(testAltClassInstance.isReady).toBe(false); + }); + + it('waits for directives ready: multiple elements', async () => { + const secondResult = createAndRegisterInstance(); + const thirdResult = createAndRegisterInstance(); + thirdResult.element.classList.remove(cssClassName); // Remove the class so the element and instance aren't treated. + + const parent = document.createElement('div'); + parent.appendChild(element); + parent.appendChild(secondResult.element); + parent.appendChild(thirdResult.element); + + expect(testClassInstance.isReady).toBe(false); + expect(testClassSecondInstance.isReady).toBe(false); + expect(testAltClassInstance.isReady).toBe(false); + expect(secondResult.instance.isReady).toBe(false); + expect(thirdResult.instance.isReady).toBe(false); + + await CoreDirectivesRegistry.waitDirectivesReady(parent, `.${cssClassName}`, DirectivesRegistryTestClass); + + expect(testClassInstance.isReady).toBe(true); + expect(testClassSecondInstance.isReady).toBe(true); + expect(testAltClassInstance.isReady).toBe(false); + expect(secondResult.instance.isReady).toBe(true); + expect(thirdResult.instance.isReady).toBe(false); + }); + +}); + +class DirectivesRegistryTestClass { + + randomId = Math.random(); + isReady = false; + + async ready(): Promise { + await wait(50); + + this.isReady = true; + } + +} + +class DirectivesRegistryAltTestClass { + + randomId = Math.random(); + isReady = false; + + async ready(): Promise { + await wait(50); + + this.isReady = true; + } + +} diff --git a/src/testing/services/behat-runtime.ts b/src/testing/services/behat-runtime.ts index 0f7eb5052..4970daaed 100644 --- a/src/testing/services/behat-runtime.ts +++ b/src/testing/services/behat-runtime.ts @@ -23,7 +23,7 @@ import { CoreNetwork, CoreNetworkService } from '@services/network'; import { CorePushNotifications, CorePushNotificationsProvider } from '@features/pushnotifications/services/pushnotifications'; import { CoreCronDelegate, CoreCronDelegateService } from '@services/cron'; import { CoreLoadingComponent } from '@components/loading/loading'; -import { CoreComponentsRegistry } from '@singletons/components-registry'; +import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDom } from '@singletons/dom'; import { Injectable } from '@angular/core'; import { CoreSites, CoreSitesProvider } from '@services/sites'; @@ -127,7 +127,7 @@ export class TestingBehatRuntimeService { .filter((element) => CoreDom.isElementVisible(element)); await Promise.all(elements.map(element => - CoreComponentsRegistry.waitComponentReady(element, CoreLoadingComponent))); + CoreDirectivesRegistry.waitDirectiveReady(element, CoreLoadingComponent))); }); }