From 4a7855895b0c34493690d5a89ae625aed76b1c34 Mon Sep 17 00:00:00 2001 From: 4gray Date: Sat, 28 Mar 2026 15:44:17 +0100 Subject: [PATCH] feat(tests): update Jest configuration for ESM support and add new test setups for playlist-shared-ui --- apps/web/jest.config.ts | 48 +++++++++++++++------- apps/web/project.json | 14 +++++-- apps/web/src/test-setup.ts | 22 +++++++++- apps/web/tsconfig.spec.json | 19 ++++++--- libs/playlist/shared/ui/jest.config.ts | 21 ++++++++++ libs/playlist/shared/ui/project.json | 8 ++++ libs/playlist/shared/ui/src/test-setup.ts | 6 +++ libs/playlist/shared/ui/tsconfig.spec.json | 17 ++++++++ libs/portal/shared/ui/src/index.ts | 1 + libs/ui/components/project.json | 13 ++++-- 10 files changed, 142 insertions(+), 27 deletions(-) create mode 100644 libs/playlist/shared/ui/jest.config.ts create mode 100644 libs/playlist/shared/ui/src/test-setup.ts create mode 100644 libs/playlist/shared/ui/tsconfig.spec.json diff --git a/apps/web/jest.config.ts b/apps/web/jest.config.ts index 4b1f54582..03d06d9c7 100644 --- a/apps/web/jest.config.ts +++ b/apps/web/jest.config.ts @@ -1,21 +1,41 @@ +import { nxPreset } from '@nx/jest/preset'; +import { createEsmPreset } from 'jest-preset-angular/presets'; + +const angularEsmPreset = createEsmPreset({ + diagnostics: false, + tsconfig: '/tsconfig.spec.json', +}); + export default { + ...nxPreset, + ...angularEsmPreset, displayName: 'web', - preset: '../../jest.preset.js', setupFilesAfterEnv: ['/src/test-setup.ts'], coverageDirectory: '../../coverage/apps/web', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], + resolver: nxPreset.resolver, + moduleFileExtensions: Array.from( + new Set([ + ...(nxPreset.moduleFileExtensions ?? []), + ...(angularEsmPreset.moduleFileExtensions ?? []), + ]) + ), + testMatch: nxPreset.testMatch, + testEnvironmentOptions: {}, + snapshotSerializers: angularEsmPreset.snapshotSerializers, + moduleNameMapper: { + ...(angularEsmPreset.moduleNameMapper ?? {}), + '^@iptvnator/portal/xtream/feature$': + '/src/test-stubs/xtream-feature.stub.ts', + tslib: 'tslib/tslib.es6.js', + '^iptv-playlist-parser$': + '/src/test-stubs/iptv-playlist-parser.mjs', + '^rxjs': '/../../node_modules/rxjs/dist/bundles/rxjs.umd.js', + '^uuid$': '/../../node_modules/uuid/wrapper.mjs', }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', + transform: angularEsmPreset.transform, + transformIgnorePatterns: [], + extensionsToTreatAsEsm: angularEsmPreset.extensionsToTreatAsEsm, + coverageReporters: [ + ...(nxPreset.coverageReporters ?? []), ], }; diff --git a/apps/web/project.json b/apps/web/project.json index 65e7ed4ee..f7fc73009 100644 --- a/apps/web/project.json +++ b/apps/web/project.json @@ -131,11 +131,19 @@ "executor": "@nx/eslint:lint" }, "test": { - "executor": "@nx/jest:jest", + "executor": "nx:run-commands", "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/web/jest.config.ts", - "tsConfig": "apps/web/tsconfig.spec.json" + "command": [ + "node", + "./node_modules/jest/bin/jest.js", + "--config", + "apps/web/jest.config.ts" + ], + "env": { + "NODE_OPTIONS": "--experimental-vm-modules" + }, + "forwardAllArgs": true } }, "serve-static": { diff --git a/apps/web/src/test-setup.ts b/apps/web/src/test-setup.ts index ea414013f..5506c1d45 100644 --- a/apps/web/src/test-setup.ts +++ b/apps/web/src/test-setup.ts @@ -1,4 +1,24 @@ -import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'; +import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone/index.mjs'; + +Object.defineProperty(globalThis, 'jest', { + configurable: true, + value: import.meta.jest, +}); + +if (typeof (globalThis as { IDBFactory?: unknown }).IDBFactory === 'undefined') { + Object.defineProperty(globalThis, 'IDBFactory', { + configurable: true, + value: class MockIDBFactory {}, + }); +} + +if (!Element.prototype.animate) { + Element.prototype.animate = () => + ({ + cancel: () => undefined, + finished: Promise.resolve(), + }) as unknown as Animation; +} setupZoneTestEnv({ errorOnUnknownElements: true, diff --git a/apps/web/tsconfig.spec.json b/apps/web/tsconfig.spec.json index d40306e4b..fd45b3daa 100644 --- a/apps/web/tsconfig.spec.json +++ b/apps/web/tsconfig.spec.json @@ -2,10 +2,11 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "../../dist/out-tsc", - "module": "commonjs", - "target": "es2016", + "module": "ESNext", + "target": "ESNext", + "esModuleInterop": true, "types": ["jest", "node"], - "moduleResolution": "node10" + "moduleResolution": "bundler" }, "files": ["src/test-setup.ts", "../../global.d.ts"], "include": [ @@ -13,8 +14,14 @@ "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts", - "../../libs/services/src/lib/epg.service.spec.ts", - "../../libs/ui/components/src/lib/confirm-dialog/dialog.service.spec.ts", - "../../libs/ui/pipes/src/lib/moment-date.pipe.spec.ts" + "../../libs/services/src/**/*.test.ts", + "../../libs/services/src/**/*.spec.ts", + "../../libs/services/src/**/*.d.ts", + "../../libs/ui/components/src/**/*.test.ts", + "../../libs/ui/components/src/**/*.spec.ts", + "../../libs/ui/components/src/**/*.d.ts", + "../../libs/ui/pipes/src/**/*.test.ts", + "../../libs/ui/pipes/src/**/*.spec.ts", + "../../libs/ui/pipes/src/**/*.d.ts" ] } diff --git a/libs/playlist/shared/ui/jest.config.ts b/libs/playlist/shared/ui/jest.config.ts new file mode 100644 index 000000000..b10246ac2 --- /dev/null +++ b/libs/playlist/shared/ui/jest.config.ts @@ -0,0 +1,21 @@ +export default { + displayName: 'playlist-shared-ui', + preset: '../../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../../coverage/libs/playlist/shared/ui', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/libs/playlist/shared/ui/project.json b/libs/playlist/shared/ui/project.json index 112df7353..81a410ea8 100644 --- a/libs/playlist/shared/ui/project.json +++ b/libs/playlist/shared/ui/project.json @@ -6,6 +6,14 @@ "projectType": "library", "tags": ["scope:playlist", "domain:m3u", "type:ui"], "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/playlist/shared/ui/jest.config.ts", + "tsConfig": "libs/playlist/shared/ui/tsconfig.spec.json" + } + }, "lint": { "executor": "@nx/eslint:lint" } diff --git a/libs/playlist/shared/ui/src/test-setup.ts b/libs/playlist/shared/ui/src/test-setup.ts new file mode 100644 index 000000000..0d88648e3 --- /dev/null +++ b/libs/playlist/shared/ui/src/test-setup.ts @@ -0,0 +1,6 @@ +import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'; + +setupZoneTestEnv({ + errorOnUnknownElements: true, + errorOnUnknownProperties: true, +}); diff --git a/libs/playlist/shared/ui/tsconfig.spec.json b/libs/playlist/shared/ui/tsconfig.spec.json new file mode 100644 index 000000000..c0bb248be --- /dev/null +++ b/libs/playlist/shared/ui/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../../dist/out-tsc", + "module": "commonjs", + "target": "es2016", + "types": ["jest", "node"], + "moduleResolution": "node10" + }, + "files": ["src/test-setup.ts"], + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/libs/portal/shared/ui/src/index.ts b/libs/portal/shared/ui/src/index.ts index 2009f319b..b740dda24 100644 --- a/libs/portal/shared/ui/src/index.ts +++ b/libs/portal/shared/ui/src/index.ts @@ -12,5 +12,6 @@ export * from './lib/components/search-form/search-form.component'; export * from './lib/components/search-layout/search-layout.component'; export { WatchedBadgeComponent } from 'components'; export * from './lib/components/unified-collection/unified-collection-page.component'; +export * from './lib/components/unified-collection/unified-live-tab.component'; export * from './lib/navigation/navigation.component'; export * from './lib/navigation/portal-rail-links.component'; diff --git a/libs/ui/components/project.json b/libs/ui/components/project.json index 202aec5fa..305d26560 100644 --- a/libs/ui/components/project.json +++ b/libs/ui/components/project.json @@ -7,11 +7,18 @@ "tags": ["scope:shared", "domain:shared-ui", "type:ui"], "targets": { "test": { - "executor": "@nx/jest:jest", + "executor": "nx:run-commands", "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "libs/ui/components/jest.config.ts", - "tsConfig": "libs/ui/components/tsconfig.spec.json" + "command": [ + "node", + "./tools/testing/run-web-esm-lib-tests.mjs", + "libs/ui/components/src" + ], + "env": { + "NODE_OPTIONS": "--experimental-vm-modules" + }, + "forwardAllArgs": true } }, "lint": {