From c4c59f11e67d8a32ddf52a1c09d64f9449371388 Mon Sep 17 00:00:00 2001 From: sumeyye Date: Tue, 30 Jun 2026 13:18:42 +0300 Subject: [PATCH] fix: UI tests in the theme shared package relating the ng v22 upgrade --- .../src/lib/tests/button.component.spec.ts | 32 +++++++++---------- .../src/lib/tests/card-body.component.spec.ts | 22 +++++++------ .../lib/tests/card-footer.component.spec.ts | 24 ++++++++------ .../lib/tests/card-header.component.spec.ts | 22 +++++++------ .../lib/tests/card-header.directive.spec.ts | 11 +++---- .../src/lib/tests/checkbox.component.spec.ts | 18 +++++++---- .../src/lib/tests/ellipsis.directive.spec.ts | 27 +++++++++++----- .../lib/tests/form-input.component.spec.ts | 20 ++++++------ .../lib/tests/loader-bar.component.spec.ts | 22 ++++++------- .../src/lib/tests/loading.directive.spec.ts | 21 +++++++----- .../src/lib/tests/toaster.service.spec.ts | 7 ++-- 11 files changed, 130 insertions(+), 96 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/button.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/button.component.spec.ts index 73ae89d96d..d0dbdb996d 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/button.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/button.component.spec.ts @@ -1,19 +1,25 @@ +import { ɵSIGNAL as SIGNAL } from '@angular/core'; import { createHostFactory, SpectatorHost } from '@ngneat/spectator/vitest'; import { ButtonComponent } from '../components'; +const setInputSignal = (inputSignal: () => T, value: T) => { + const node = inputSignal[SIGNAL]; + node.applyValueToInputSignal(node, value); +}; + describe('ButtonComponent', () => { let spectator: SpectatorHost; const createHost = createHostFactory(ButtonComponent); beforeEach( - () => - (spectator = createHost( - 'Button', - { - hostProps: { attributes: { autofocus: '', name: 'abp-button' } }, - }, - )), + () => { + spectator = createHost('Button', { + detectChanges: false, + }); + setInputSignal(spectator.component.iconClass, 'fa fa-check'); + spectator.detectChanges(); + }, ); it('should display the button', () => { @@ -48,23 +54,17 @@ describe('ButtonComponent', () => { }); it('should display the spinner icon when loading input is true', () => { - spectator = createHost( - 'Button', - { hostProps: { loading: true } }, - ); + setInputSignal(spectator.component.loading, true); spectator.detectComponentChanges(); expect(spectator.query('i')).toHaveClass('fa-spinner'); }); it('should clear the spinner icon when loading input becomes false', () => { - spectator = createHost( - 'Button', - { hostProps: { loading: true } }, - ); + setInputSignal(spectator.component.loading, true); spectator.detectComponentChanges(); expect(spectator.query('i')).toHaveClass('fa-spinner'); - spectator.setHostInput({ loading: false }); + setInputSignal(spectator.component.loading, false); spectator.detectComponentChanges(); expect(spectator.query('i')).toHaveClass('fa-check'); expect(spectator.query('i')).not.toHaveClass('fa-spinner'); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/card-body.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/card-body.component.spec.ts index 83cc302625..efe1d6fc04 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/card-body.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/card-body.component.spec.ts @@ -1,5 +1,6 @@ import { createHostFactory, SpectatorHost } from '@ngneat/spectator'; import { CardBodyComponent } from '../components'; +import { setInputSignal } from './utils'; describe('AbpCardBodyComponent', () => { let spectator: SpectatorHost; @@ -8,16 +9,17 @@ describe('AbpCardBodyComponent', () => { beforeEach( () => - (spectator = createHost( - ` -

Body

-
`, - { - hostProps: { attributes: { autofocus: '', name: 'abp-card-body' } }, - }, - )), + { + spectator = createHost( + `

Body

`, + { + detectChanges: false, + hostProps: { attributes: { autofocus: '', name: 'abp-card-body' } }, + }, + ); + setInputSignal(spectator.component.cardBodyStyle, 'background-color: red;'); + spectator.detectChanges(); + }, ); it('should create an instance', () => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/card-footer.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/card-footer.component.spec.ts index 2b98479b9f..2e7074ce58 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/card-footer.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/card-footer.component.spec.ts @@ -1,5 +1,6 @@ import { createHostFactory, SpectatorHost } from '@ngneat/spectator'; import { CardFooterComponent } from '../components'; +import { setInputSignal } from './utils'; describe('AbpCardFooterComponent', () => { let spectator: SpectatorHost; @@ -8,16 +9,19 @@ describe('AbpCardFooterComponent', () => { beforeEach( () => - (spectator = createHost( - ` -

Footer

-
`, - { - hostProps: { attributes: { autofocus: '', name: 'abp-card-footer' } }, - }, - )), + { + spectator = createHost( + ` +

Footer

+
`, + { + detectChanges: false, + hostProps: { attributes: { autofocus: '', name: 'abp-card-footer' } }, + }, + ); + setInputSignal(spectator.component.cardFooterStyle, 'background-color: red;'); + spectator.detectChanges(); + }, ); it('should create an instance', () => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.component.spec.ts index 279cfe90bf..1c75c588ce 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.component.spec.ts @@ -1,5 +1,6 @@ import { createHostFactory, SpectatorHost } from '@ngneat/spectator'; import { CardHeaderComponent } from '../components'; +import { setInputSignal } from './utils'; describe('AbpCardHeaderComponent', () => { let spectator: SpectatorHost; @@ -7,16 +8,17 @@ describe('AbpCardHeaderComponent', () => { beforeEach( () => - (spectator = createHost( - ` - Header - `, - { - hostProps: { attributes: { autofocus: '', name: 'abp-card-header' } }, - }, - )), + { + spectator = createHost( + ` Header `, + { + detectChanges: false, + hostProps: { attributes: { autofocus: '', name: 'abp-card-header' } }, + }, + ); + setInputSignal(spectator.component.cardHeaderStyle, 'background-color: red;'); + spectator.detectChanges(); + }, ); it('should create an instance', () => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.directive.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.directive.spec.ts index 122de05ed8..08a99323e6 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.directive.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/card-header.directive.spec.ts @@ -7,15 +7,14 @@ describe('AbpCardHeaderDirective', () => { const createHost = createHostFactory(CardHeaderDirective); beforeEach( - () => - (spectator = createHost( - `
-
`, + () => { + spectator = createHost( + `
`, { hostProps: { attributes: { autofocus: '', name: 'abp-card-header' } }, }, - )), + ); + }, ); it('should create an instance', () => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/checkbox.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/checkbox.component.spec.ts index 4ea0946c01..e983eb7bbb 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/checkbox.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/checkbox.component.spec.ts @@ -1,5 +1,6 @@ import { createHostFactory, SpectatorHost } from '@ngneat/spectator/vitest'; import { FormCheckboxComponent } from '../components/checkbox/checkbox.component'; +import { setInputSignal } from './utils'; describe('FormCheckboxComponent', () => { let spectator: SpectatorHost; @@ -7,13 +8,18 @@ describe('FormCheckboxComponent', () => { const createHost = createHostFactory(FormCheckboxComponent); beforeEach( - () => - (spectator = createHost( - '', + () => { + spectator = createHost( + '', { + detectChanges: false, hostProps: { attributes: { autofocus: '', name: 'abp-checkbox' } }, }, - )), + ); + setInputSignal(spectator.component.checkboxId, 'checkbox-id'); + setInputSignal(spectator.component.checkboxReadonly, true); + spectator.detectChanges(); + }, ); it('should display the input', () => { @@ -29,13 +35,13 @@ describe('FormCheckboxComponent', () => { }); it('should be readonly when checkboxReadonly is true', () => { - spectator.component.checkboxReadonly = true; + setInputSignal(spectator.component.checkboxReadonly, true); spectator.detectComponentChanges(); expect(spectator.query('[readonly]')).toBeTruthy(); }); it('should not contain readonly when checboxReadonly is false', () => { - spectator.component.checkboxReadonly = false; + setInputSignal(spectator.component.checkboxReadonly, false); spectator.detectComponentChanges(); expect(spectator.query('[disabled]')).toBeFalsy(); }); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/ellipsis.directive.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/ellipsis.directive.spec.ts index e9b0e45a0d..438675fb8c 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/ellipsis.directive.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/ellipsis.directive.spec.ts @@ -1,5 +1,6 @@ import { createDirectiveFactory, SpectatorDirective } from '@ngneat/spectator/vitest'; import { EllipsisDirective } from '../directives/ellipsis.directive'; +import { setInputSignal } from './utils'; describe('EllipsisDirective', () => { let spectator: SpectatorDirective; @@ -13,12 +14,13 @@ describe('EllipsisDirective', () => { spectator = createDirective( '
test content
', { - hostProps: { - title: 'test title', - width: '100px', - }, + detectChanges: false, }, ); + setInputSignal(spectator.directive.width, '100px'); + setInputSignal(spectator.directive.enabled, true); + setInputSignal(spectator.directive.title, 'title'); + spectator.detectChanges(); directive = spectator.directive; el = spectator.query('div'); }); @@ -28,15 +30,15 @@ describe('EllipsisDirective', () => { }); test('should have 100px ellipsis width', () => { - expect(directive.width).toBe('100px'); + expect(directive.width()).toBe('100px'); }); test('should be enabled if abpEllipsisEnabled input is true', () => { - expect(directive.enabled).toBe(true); + expect(directive.enabled()).toBe(true); }); test('should have given title', () => { - expect(directive.title).toBe('test title'); + expect(directive.title()).toBe('title'); }); test('should add abp-ellipsis-inline class to element if width is given', () => { @@ -48,6 +50,7 @@ describe('EllipsisDirective when title is not specified', () => { let spectator: SpectatorDirective; let directive: EllipsisDirective; let el: HTMLDivElement; + const createDirective = createDirectiveFactory({ directive: EllipsisDirective, }); @@ -62,12 +65,16 @@ describe('EllipsisDirective when title is not specified', () => { }, }, ); + setInputSignal(spectator.directive.width, '100px'); + setInputSignal(spectator.directive.enabled, true); + setInputSignal(spectator.directive.title, undefined); + spectator.detectChanges(); directive = spectator.directive; el = spectator.query('div') as HTMLDivElement; }); test('should have element innerText as title', () => { - expect(directive.title).toBe(el.innerText); + expect(directive.title()).toBe(el.innerText); }); }); @@ -89,6 +96,10 @@ describe('EllipsisDirective when width is not given', () => { }, }, ); + setInputSignal(spectator.directive.width, undefined); + setInputSignal(spectator.directive.enabled, true); + setInputSignal(spectator.directive.title, 'test title'); + spectator.detectChanges(); directive = spectator.directive; el = spectator.query('div') as HTMLDivElement; }); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/form-input.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/form-input.component.spec.ts index e6ae275a95..8e35e4c7b7 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/form-input.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/form-input.component.spec.ts @@ -1,5 +1,6 @@ import { createHostFactory, SpectatorHost } from '@ngneat/spectator/vitest'; import { FormInputComponent } from '../components/form-input/form-input.component'; +import { setInputSignal } from './utils'; describe('FormInputComponent', () => { @@ -8,13 +9,14 @@ describe('FormInputComponent', () => { const createHost = createHostFactory(FormInputComponent); beforeEach( - () => - (spectator = createHost( - '', - { - hostProps: { attributes: { autofocus: '', name: 'abp-form-input' } }, - }, - )), + () => { + spectator = createHost( + '', + { + hostProps: { attributes: { autofocus: '', name: 'abp-form-input' } }, + }, + ); + }, ); it('should display the input', () => { @@ -30,13 +32,13 @@ describe('FormInputComponent', () => { }); it('should be readonly when inputReadonly is true', () => { - spectator.component.inputReadonly = true; + setInputSignal(spectator.component.inputReadonly, true); spectator.detectComponentChanges(); expect(spectator.query('[readonly]')).toBeTruthy(); }); it('should not contain readonly when inputReadonly is false', () => { - spectator.component.inputReadonly = false; + setInputSignal(spectator.component.inputReadonly, false); spectator.detectComponentChanges(); expect(spectator.query('[disabled]')).toBeFalsy(); }); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts index a825cbf7db..eb2feddddb 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/loader-bar.component.spec.ts @@ -4,7 +4,8 @@ import { NavigationStart, Router } from '@angular/router'; import { createComponentFactory, Spectator } from '@ngneat/spectator/vitest'; import { combineLatest, firstValueFrom, Subject, timer } from 'rxjs'; import { LoaderBarComponent } from '../components/loader-bar/loader-bar.component'; -import { setupComponentResources } from './utils'; +import { setupComponentResources, setInputSignal } from './utils'; + describe('LoaderBarComponent', () => { let spectator: Spectator; @@ -34,8 +35,8 @@ describe('LoaderBarComponent', () => { }); it('should initial variable values are correct', () => { - expect(spectator.component.containerClass).toBe('abp-loader-bar'); - expect(spectator.component.color).toBe('#77b6ff'); + expect(spectator.component.containerClass()).toBe('abp-loader-bar'); + expect(spectator.component.color()).toBe('#77b6ff'); }); it('should increase the progressLevel', async () => { @@ -45,8 +46,7 @@ describe('LoaderBarComponent', () => { spectator.detectChanges(); await new Promise(resolve => setTimeout(resolve, 10)); - - expect(spectator.component.progressLevel > 0).toBeTruthy(); + expect(spectator.component.progressLevel()).toBeGreaterThan(0); }); @@ -100,15 +100,15 @@ describe('LoaderBarComponent', () => { spectator.detectChanges(); attempts = 0; - while (spectator.component.progressLevel !== 100 && attempts < 50) { + while (spectator.component.progressLevel() !== 100 && attempts < 50) { await new Promise(resolve => setTimeout(resolve, 10)); spectator.detectChanges(); attempts++; } - expect(spectator.component.progressLevel).toBe(100); + expect(spectator.component.progressLevel()).toBe(100); await firstValueFrom(timer(spectator.component.stopDelay + 10)); - expect(spectator.component.progressLevel).toBe(0); + expect(spectator.component.progressLevel()).toBe(0); }); it('should stop the loading with navigation', async () => { @@ -130,15 +130,15 @@ describe('LoaderBarComponent', () => { spectator.detectChanges(); attempts = 0; - while (spectator.component.progressLevel !== 100 && attempts < 50) { + while (spectator.component.progressLevel() !== 100 && attempts < 50) { await new Promise(resolve => setTimeout(resolve, 10)); spectator.detectChanges(); attempts++; } - expect(spectator.component.progressLevel).toBe(100); + expect(spectator.component.progressLevel()).toBe(100); await firstValueFrom(timer(spectator.component.stopDelay + 10)); - expect(spectator.component.progressLevel).toBe(0); + expect(spectator.component.progressLevel()).toBe(0); }); describe('#startLoading', () => { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts index f80388d478..638584612f 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/loading.directive.spec.ts @@ -1,7 +1,8 @@ +import { Component } from '@angular/core'; import { SpectatorDirective, createDirectiveFactory } from '@ngneat/spectator/vitest'; import { LoadingDirective } from '../directives'; import { LoadingComponent } from '../components'; -import { Component } from '@angular/core'; +import { setInputSignal } from './utils'; @Component({ selector: 'abp-dummy', @@ -30,10 +31,10 @@ describe('LoadingDirective', () => { }); it('should handle loading input', async () => { - spectator.directive.loading = false; + setInputSignal(spectator.directive.loading, false); await new Promise(resolve => setTimeout(resolve, 10)); expect(spectator.directive).toBeTruthy(); - expect(spectator.directive.loading).toBe(false); + expect(spectator.directive.loading()).toBe(false); }); }); @@ -42,11 +43,15 @@ describe('LoadingDirective', () => { beforeEach(() => { spectator = createDirective( - '
Testing Loading Directive
', + '
Testing Loading Directive
', { - hostProps: { loading: true, target: mockTarget, delay: 0 }, + detectChanges: false, }, ); + setInputSignal(spectator.directive.loading, true); + setInputSignal(spectator.directive.delay, 0); + setInputSignal(spectator.directive.targetElementInput, mockTarget); + spectator.detectChanges(); }); it('should create directive with custom target', () => { @@ -55,17 +60,17 @@ describe('LoadingDirective', () => { }); it('should handle delay input', async () => { - spectator.directive.delay = 100; + setInputSignal(spectator.directive.delay, 100); await new Promise(resolve => setTimeout(resolve, 10)); expect(spectator.directive).toBeTruthy(); }); it('should handle loading state changes', async() => { - spectator.directive.loading = false; + setInputSignal(spectator.directive.loading, false); await new Promise(resolve => setTimeout(resolve, 10)); expect(spectator.directive).toBeTruthy(); - spectator.directive.loading = true; + setInputSignal(spectator.directive.loading, true); await new Promise(resolve => setTimeout(resolve, 10)); expect(spectator.directive).toBeTruthy(); }); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts index 401da50070..0259bbd945 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts @@ -8,10 +8,13 @@ import { ToasterService } from '../services/toaster.service'; describe('ToasterService', () => { let spectator: SpectatorService; let service: ToasterService; + const mockComponentRef = { changeDetectorRef: { detectChanges: vi.fn() }, - instance: {} as ToastContainerComponent, - } as unknown as ComponentRef; + instance: { + setToasts: vi.fn(), remove: vi.fn(), toasts: [], top: 0, right: 0, bottom: 0, left: 0, + }, + }; const contentProjectionService = { projectContent: vi.fn().mockReturnValue(mockComponentRef),