From 2a83c2e8282b8ca1e760dd682db808ac22c9f552 Mon Sep 17 00:00:00 2001 From: sumeyye Date: Tue, 20 Jan 2026 15:41:18 +0300 Subject: [PATCH] update: theme-basic package tests --- .../src/lib/tests/lazy-style.handler.spec.ts | 70 +++++++++++++++---- .../theme-basic/src/lib/tests/test-utils.ts | 54 ++++++++++++++ .../packages/theme-basic/src/test-setup.ts | 22 +++++- .../packages/theme-basic/vitest.config.mts | 1 + 4 files changed, 130 insertions(+), 17 deletions(-) create mode 100644 npm/ng-packs/packages/theme-basic/src/lib/tests/test-utils.ts diff --git a/npm/ng-packs/packages/theme-basic/src/lib/tests/lazy-style.handler.spec.ts b/npm/ng-packs/packages/theme-basic/src/lib/tests/lazy-style.handler.spec.ts index dd0591f9fd..e2e910c5d7 100644 --- a/npm/ng-packs/packages/theme-basic/src/lib/tests/lazy-style.handler.spec.ts +++ b/npm/ng-packs/packages/theme-basic/src/lib/tests/lazy-style.handler.spec.ts @@ -1,23 +1,59 @@ -import { LazyLoadService, LOADING_STRATEGY, LocalizationService } from '@abp/ng.core'; +import { DOCUMENT } from '@angular/common'; +import { createServiceFactory, SpectatorService } from '@ngneat/spectator/vitest'; +import { of, Subject } from 'rxjs'; +import { vi } from 'vitest'; + +import { LazyLoadService, LoadingStrategy, LocalizationService } from '@abp/ng.core'; import { DocumentDirHandlerService } from '@abp/ng.theme.shared'; -import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest'; -import { of } from 'rxjs'; import { BOOTSTRAP, createLazyStyleHref, LazyStyleHandler } from '../handlers'; - -const currentLang$ = of({ payload: 'en' }); +import { LAZY_STYLES } from '../tokens/lazy-styles.token'; +import { setupComponentResources } from './test-utils'; describe('LazyStyleHandler', () => { let spectator: SpectatorService; let handler: LazyStyleHandler; - let lazyLoad: LazyLoadService; + let lazyLoad: any; + + beforeAll(async () => { + await setupComponentResources( + '../components/breadcrumb', + import.meta.url + ); + }); + + const dir$ = new Subject<'ltr' | 'rtl'>(); const createService = createServiceFactory({ service: LazyStyleHandler, providers: [ - DocumentDirHandlerService, + { + provide: DOCUMENT, + useValue: document, + }, + { + provide: LAZY_STYLES, + useValue: [BOOTSTRAP], + }, + { + provide: LazyLoadService, + useValue: { + loaded: new Map(), + load: vi.fn(() => of(null)), + remove: vi.fn(), + }, + }, + { + provide: DocumentDirHandlerService, + useValue: { + dir$, + }, + }, { provide: LocalizationService, - useValue: { currentLang: 'en', currentLang$ }, + useValue: { + currentLang: 'en', + currentLang$: of({ payload: 'en' }), + }, }, ], }); @@ -25,7 +61,7 @@ describe('LazyStyleHandler', () => { beforeEach(() => { spectator = createService(); handler = spectator.service; - lazyLoad = handler['lazyLoad']; + lazyLoad = spectator.inject(LazyLoadService); }); describe('#dir', () => { @@ -36,15 +72,19 @@ describe('LazyStyleHandler', () => { it('should set bootstrap to rtl', () => { const oldHref = createLazyStyleHref(BOOTSTRAP, 'ltr'); const newHref = createLazyStyleHref(BOOTSTRAP, 'rtl'); - lazyLoad.loaded.set(newHref, null); // avoid actual loading - const load = jest.spyOn(lazyLoad, 'load'); - const remove = jest.spyOn(lazyLoad, 'remove'); - const strategy = LOADING_STRATEGY.PrependAnonymousStyleToHead(newHref); + + lazyLoad.loaded.set(newHref, null); + + const loadSpy = vi.spyOn(lazyLoad, 'load'); + const removeSpy = vi.spyOn(lazyLoad, 'remove'); handler.dir = 'rtl'; - expect(load).toHaveBeenCalledWith(strategy); - expect(remove).toHaveBeenCalledWith(oldHref); + expect(loadSpy).toHaveBeenCalledTimes(1); + const [strategy] = loadSpy.mock.calls[0]; + expect((strategy as LoadingStrategy).path).toBe(newHref); + + expect(removeSpy).toHaveBeenCalledWith(oldHref); }); }); }); diff --git a/npm/ng-packs/packages/theme-basic/src/lib/tests/test-utils.ts b/npm/ng-packs/packages/theme-basic/src/lib/tests/test-utils.ts new file mode 100644 index 0000000000..ac9c9eff50 --- /dev/null +++ b/npm/ng-packs/packages/theme-basic/src/lib/tests/test-utils.ts @@ -0,0 +1,54 @@ +import { readFileSync } from 'node:fs'; +import { resolve, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +/** + * Sets up component resource resolution for Angular component tests. + * This is needed when components have external templates or stylesheets. + * + * @param componentDirPath - The path to the component directory relative to the test file. + * For example: '../components/loader-bar' or './components/my-component' + * @param testFileUrl - The import.meta.url from the test file. Defaults to the caller's location. + * + * @example + * ```typescript + * + * import { setupComponentResources } from './test-utils'; + * + * beforeAll(() => setupComponentResources('../components/loader-bar', import.meta.url)); + * ``` + */ +export async function setupComponentResources( + componentDirPath: string, + testFileUrl: string = import.meta.url, +): Promise { + try { + if (typeof process !== 'undefined' && process.versions?.node) { + const { ɵresolveComponentResources: resolveComponentResources } = await import('@angular/core'); + + // Get the test file directory path + const testFileDir = dirname(fileURLToPath(testFileUrl)); + const componentDir = resolve(testFileDir, componentDirPath); + + await resolveComponentResources((url: string) => { + // For SCSS/SASS files, return empty CSS since jsdom can't parse SCSS + if (url.endsWith('.scss') || url.endsWith('.sass')) { + return Promise.resolve(''); + } + + // For other files (HTML, CSS, etc.), read the actual content + try { + // Resolve relative paths like './component.scss' or 'component.scss' + const normalizedUrl = url.replace(/^\.\//, ''); + const filePath = resolve(componentDir, normalizedUrl); + return Promise.resolve(readFileSync(filePath, 'utf-8')); + } catch (error) { + // If file not found, return empty string + return Promise.resolve(''); + } + }); + } + } catch (error) { + console.warn('Failed to set up component resource resolver:', error); + } +} diff --git a/npm/ng-packs/packages/theme-basic/src/test-setup.ts b/npm/ng-packs/packages/theme-basic/src/test-setup.ts index 4555f138a7..b349bcf687 100644 --- a/npm/ng-packs/packages/theme-basic/src/test-setup.ts +++ b/npm/ng-packs/packages/theme-basic/src/test-setup.ts @@ -1,2 +1,20 @@ -import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'; -setupZoneTestEnv(); +import '@angular/compiler'; +import 'zone.js'; +import 'zone.js/testing'; +import { getTestBed } from '@angular/core/testing'; +import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing'; + +// Initialize Angular testing environment +getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting()); + +// Mock window.location for test environment +Object.defineProperty(window, 'location', { + value: { + href: 'http://localhost:4200', + origin: 'http://localhost:4200', + pathname: '/', + search: '', + hash: '', + }, + writable: true, +}); diff --git a/npm/ng-packs/packages/theme-basic/vitest.config.mts b/npm/ng-packs/packages/theme-basic/vitest.config.mts index 569595197b..f76013d8f4 100644 --- a/npm/ng-packs/packages/theme-basic/vitest.config.mts +++ b/npm/ng-packs/packages/theme-basic/vitest.config.mts @@ -11,6 +11,7 @@ export default defineConfig(() => ({ watch: false, globals: true, environment: 'jsdom', + setupFiles: ['src/test-setup.ts'], include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], reporters: ['default'], coverage: {