diff --git a/goldens/public-api/angular/build/index.api.md b/goldens/public-api/angular/build/index.api.md index 6e01517ec550..99222d988433 100644 --- a/goldens/public-api/angular/build/index.api.md +++ b/goldens/public-api/angular/build/index.api.md @@ -228,6 +228,7 @@ export type UnitTestBuilderOptions = { providersFile?: string; reporters?: string[]; runner: Runner; + setupFiles?: string[]; tsConfig: string; watch?: boolean; }; diff --git a/packages/angular/build/src/builders/unit-test/builder.ts b/packages/angular/build/src/builders/unit-test/builder.ts index f056dd4d10b0..014d41cffb64 100644 --- a/packages/angular/build/src/builders/unit-test/builder.ts +++ b/packages/angular/build/src/builders/unit-test/builder.ts @@ -197,9 +197,11 @@ export async function* execute( } // Add setup file entries for TestBed initialization and project polyfills - const setupFiles = ['init-testbed.js']; + const setupFiles = ['init-testbed.js', ...normalizedOptions.setupFiles]; if (buildTargetOptions?.polyfills?.length) { - setupFiles.push('polyfills.js'); + // Placed first as polyfills may be required by the Testbed initialization + // or other project provided setup files (e.g., zone.js, ECMAScript polyfills). + setupFiles.unshift('polyfills.js'); } const debugOptions = normalizedOptions.debug ? { diff --git a/packages/angular/build/src/builders/unit-test/karma-bridge.ts b/packages/angular/build/src/builders/unit-test/karma-bridge.ts index 4fa7b085802c..7bfe9a1ebe94 100644 --- a/packages/angular/build/src/builders/unit-test/karma-bridge.ts +++ b/packages/angular/build/src/builders/unit-test/karma-bridge.ts @@ -21,6 +21,12 @@ export async function useKarmaBuilder( ); } + if (unitTestOptions.setupFiles.length) { + context.logger.warn( + 'The "karma" test runner does not support the "setupFiles" option. The option will be ignored.', + ); + } + const buildTargetOptions = (await context.validateOptions( await context.getTargetOptions(unitTestOptions.buildTarget), await context.getBuilderNameForTarget(unitTestOptions.buildTarget), diff --git a/packages/angular/build/src/builders/unit-test/options.ts b/packages/angular/build/src/builders/unit-test/options.ts index 43147a23c065..c1d4b8a308a1 100644 --- a/packages/angular/build/src/builders/unit-test/options.ts +++ b/packages/angular/build/src/builders/unit-test/options.ts @@ -62,6 +62,9 @@ export async function normalizeOptions( watch: options.watch ?? isTTY(), debug: options.debug ?? false, providersFile: options.providersFile && path.join(workspaceRoot, options.providersFile), + setupFiles: options.setupFiles + ? options.setupFiles.map((setupFile) => path.join(workspaceRoot, setupFile)) + : [], }; } diff --git a/packages/angular/build/src/builders/unit-test/schema.json b/packages/angular/build/src/builders/unit-test/schema.json index 93ca22b5003f..73ba94ead630 100644 --- a/packages/angular/build/src/builders/unit-test/schema.json +++ b/packages/angular/build/src/builders/unit-test/schema.json @@ -76,7 +76,14 @@ "type": "array", "minItems": 1, "maxItems": 2, - "items": [{ "$ref": "#/definitions/coverage-reporters" }, { "type": "object" }] + "items": [ + { + "$ref": "#/definitions/coverage-reporters" + }, + { + "type": "object" + } + ] } ] } @@ -92,6 +99,13 @@ "type": "string", "description": "TypeScript file that exports an array of Angular providers to use during test execution. The array must be a default export.", "minLength": 1 + }, + "setupFiles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "A list of global setup and configuration files that are included before the test files. The application's polyfills are always included before these files. The Angular Testbed is also initialized prior to the execution of these files." } }, "additionalProperties": false,