@angular/build 20.2.0 → 21.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.browserslistrc +5 -5
  2. package/package.json +15 -15
  3. package/src/builders/dev-server/builder.js +2 -2
  4. package/src/builders/dev-server/vite/hmr.d.ts +25 -0
  5. package/src/builders/dev-server/vite/hmr.js +113 -0
  6. package/src/builders/dev-server/vite/index.d.ts +21 -0
  7. package/src/builders/dev-server/{vite-server.js → vite/index.js} +19 -359
  8. package/src/builders/dev-server/vite/server.d.ts +15 -0
  9. package/src/builders/dev-server/vite/server.js +229 -0
  10. package/src/builders/dev-server/vite/utils.d.ts +36 -0
  11. package/src/builders/dev-server/vite/utils.js +76 -0
  12. package/src/builders/unit-test/builder.d.ts +1 -1
  13. package/src/builders/unit-test/builder.js +187 -289
  14. package/src/builders/unit-test/options.d.ts +1 -0
  15. package/src/builders/unit-test/options.js +2 -1
  16. package/src/builders/unit-test/runners/api.d.ts +47 -0
  17. package/src/builders/unit-test/runners/api.js +9 -0
  18. package/src/builders/unit-test/runners/karma/executor.d.ts +17 -0
  19. package/src/builders/unit-test/runners/karma/executor.js +93 -0
  20. package/src/builders/unit-test/runners/karma/index.d.ts +13 -0
  21. package/src/builders/unit-test/runners/karma/index.js +26 -0
  22. package/src/builders/unit-test/runners/vitest/browser-provider.d.ts +11 -0
  23. package/src/builders/unit-test/runners/vitest/browser-provider.js +69 -0
  24. package/src/builders/unit-test/runners/vitest/build-options.d.ts +11 -0
  25. package/src/builders/unit-test/runners/vitest/build-options.js +87 -0
  26. package/src/builders/unit-test/runners/vitest/executor.d.ts +22 -0
  27. package/src/builders/unit-test/runners/vitest/executor.js +160 -0
  28. package/src/builders/unit-test/runners/vitest/index.d.ts +13 -0
  29. package/src/builders/unit-test/runners/vitest/index.js +30 -0
  30. package/src/builders/unit-test/schema.d.ts +4 -0
  31. package/src/builders/unit-test/schema.json +4 -0
  32. package/src/builders/unit-test/test-discovery.d.ts +8 -0
  33. package/src/builders/unit-test/test-discovery.js +14 -0
  34. package/src/private.d.ts +1 -1
  35. package/src/private.js +2 -2
  36. package/src/utils/environment-options.d.ts +43 -0
  37. package/src/utils/environment-options.js +84 -30
  38. package/src/utils/normalize-cache.js +1 -1
  39. package/src/utils/version.js +1 -1
  40. package/src/builders/dev-server/vite-server.d.ts +0 -42
  41. package/src/builders/unit-test/karma-bridge.d.ts +0 -10
  42. package/src/builders/unit-test/karma-bridge.js +0 -82
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.KarmaExecutor = void 0;
44
+ class KarmaExecutor {
45
+ context;
46
+ options;
47
+ constructor(context, options) {
48
+ this.context = context;
49
+ this.options = options;
50
+ }
51
+ async *execute() {
52
+ const { context, options: unitTestOptions } = this;
53
+ if (unitTestOptions.debug) {
54
+ context.logger.warn('The "karma" test runner does not support the "debug" option. The option will be ignored.');
55
+ }
56
+ if (unitTestOptions.setupFiles.length) {
57
+ context.logger.warn('The "karma" test runner does not support the "setupFiles" option. The option will be ignored.');
58
+ }
59
+ const buildTargetOptions = (await context.validateOptions(await context.getTargetOptions(unitTestOptions.buildTarget), await context.getBuilderNameForTarget(unitTestOptions.buildTarget)));
60
+ const karmaOptions = {
61
+ tsConfig: unitTestOptions.tsConfig,
62
+ polyfills: buildTargetOptions.polyfills,
63
+ assets: buildTargetOptions.assets,
64
+ scripts: buildTargetOptions.scripts,
65
+ styles: buildTargetOptions.styles,
66
+ inlineStyleLanguage: buildTargetOptions.inlineStyleLanguage,
67
+ stylePreprocessorOptions: buildTargetOptions.stylePreprocessorOptions,
68
+ externalDependencies: buildTargetOptions.externalDependencies,
69
+ loader: buildTargetOptions.loader,
70
+ define: buildTargetOptions.define,
71
+ include: unitTestOptions.include,
72
+ exclude: unitTestOptions.exclude,
73
+ sourceMap: buildTargetOptions.sourceMap,
74
+ progress: unitTestOptions.buildProgress ?? buildTargetOptions.progress,
75
+ watch: unitTestOptions.watch,
76
+ poll: buildTargetOptions.poll,
77
+ preserveSymlinks: buildTargetOptions.preserveSymlinks,
78
+ browsers: unitTestOptions.browsers?.join(','),
79
+ codeCoverage: !!unitTestOptions.codeCoverage,
80
+ codeCoverageExclude: unitTestOptions.codeCoverage?.exclude,
81
+ fileReplacements: buildTargetOptions.fileReplacements,
82
+ reporters: unitTestOptions.reporters,
83
+ webWorkerTsConfig: buildTargetOptions.webWorkerTsConfig,
84
+ aot: buildTargetOptions.aot,
85
+ };
86
+ const { execute } = await Promise.resolve().then(() => __importStar(require('../../../karma')));
87
+ yield* execute(karmaOptions, context);
88
+ }
89
+ async [Symbol.asyncDispose]() {
90
+ // The Karma builder handles its own teardown
91
+ }
92
+ }
93
+ exports.KarmaExecutor = KarmaExecutor;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import type { TestRunner } from '../api';
9
+ /**
10
+ * A declarative definition of the Karma test runner.
11
+ */
12
+ declare const KarmaTestRunner: TestRunner;
13
+ export default KarmaTestRunner;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const executor_1 = require("./executor");
11
+ /**
12
+ * A declarative definition of the Karma test runner.
13
+ */
14
+ const KarmaTestRunner = {
15
+ name: 'karma',
16
+ isStandalone: true,
17
+ getBuildOptions() {
18
+ return {
19
+ buildOptions: {},
20
+ };
21
+ },
22
+ async createExecutor(context, options) {
23
+ return new executor_1.KarmaExecutor(context, options);
24
+ },
25
+ };
26
+ exports.default = KarmaTestRunner;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ export declare function setupBrowserConfiguration(browsers: string[] | undefined, debug: boolean, projectSourceRoot: string): {
9
+ browser?: import('vitest/node').BrowserConfigOptions;
10
+ errors?: string[];
11
+ };
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.setupBrowserConfiguration = setupBrowserConfiguration;
11
+ const node_module_1 = require("node:module");
12
+ function findBrowserProvider(projectResolver) {
13
+ // One of these must be installed in the project to use browser testing
14
+ const vitestBuiltinProviders = ['playwright', 'webdriverio'];
15
+ for (const providerName of vitestBuiltinProviders) {
16
+ try {
17
+ projectResolver(providerName);
18
+ return providerName;
19
+ }
20
+ catch { }
21
+ }
22
+ return undefined;
23
+ }
24
+ function normalizeBrowserName(browserName) {
25
+ // Normalize browser names to match Vitest's expectations for headless but also supports karma's names
26
+ // e.g., 'ChromeHeadless' -> 'chrome', 'FirefoxHeadless' -> 'firefox'
27
+ // and 'Chrome' -> 'chrome', 'Firefox' -> 'firefox'.
28
+ const normalized = browserName.toLowerCase();
29
+ return normalized.replace(/headless$/, '');
30
+ }
31
+ function setupBrowserConfiguration(browsers, debug, projectSourceRoot) {
32
+ if (browsers === undefined) {
33
+ return {};
34
+ }
35
+ const projectResolver = (0, node_module_1.createRequire)(projectSourceRoot + '/').resolve;
36
+ let errors;
37
+ try {
38
+ projectResolver('@vitest/browser');
39
+ }
40
+ catch {
41
+ errors ??= [];
42
+ errors.push('The "browsers" option requires the "@vitest/browser" package to be installed within the project.' +
43
+ ' Please install this package and rerun the test command.');
44
+ }
45
+ const provider = findBrowserProvider(projectResolver);
46
+ if (!provider) {
47
+ errors ??= [];
48
+ errors.push('The "browsers" option requires either "playwright" or "webdriverio" to be installed within the project.' +
49
+ ' Please install one of these packages and rerun the test command.');
50
+ }
51
+ // Vitest current requires the playwright browser provider to use the inspect-brk option used by "debug"
52
+ if (debug && provider !== 'playwright') {
53
+ errors ??= [];
54
+ errors.push('Debugging browser mode tests currently requires the use of "playwright".' +
55
+ ' Please install this package and rerun the test command.');
56
+ }
57
+ if (errors) {
58
+ return { errors };
59
+ }
60
+ const browser = {
61
+ enabled: true,
62
+ provider,
63
+ headless: browsers.some((name) => name.toLowerCase().includes('headless')),
64
+ instances: browsers.map((browserName) => ({
65
+ browser: normalizeBrowserName(browserName),
66
+ })),
67
+ };
68
+ return { browser };
69
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import type { ApplicationBuilderInternalOptions } from '../../../application/options';
9
+ import { NormalizedUnitTestBuilderOptions } from '../../options';
10
+ import { RunnerOptions } from '../api';
11
+ export declare function getVitestBuildOptions(options: NormalizedUnitTestBuilderOptions, baseBuildOptions: Partial<ApplicationBuilderInternalOptions>): Promise<RunnerOptions>;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.getVitestBuildOptions = getVitestBuildOptions;
14
+ const node_path_1 = __importDefault(require("node:path"));
15
+ const path_1 = require("../../../../utils/path");
16
+ const schema_1 = require("../../../application/schema");
17
+ const options_1 = require("../../options");
18
+ const test_discovery_1 = require("../../test-discovery");
19
+ function createTestBedInitVirtualFile(providersFile, projectSourceRoot) {
20
+ let providersImport = 'const providers = [];';
21
+ if (providersFile) {
22
+ const relativePath = node_path_1.default.relative(projectSourceRoot, providersFile);
23
+ const { dir, name } = node_path_1.default.parse(relativePath);
24
+ const importPath = (0, path_1.toPosixPath)(node_path_1.default.join(dir, name));
25
+ providersImport = `import providers from './${importPath}';`;
26
+ }
27
+ return `
28
+ // Initialize the Angular testing environment
29
+ import { NgModule } from '@angular/core';
30
+ import { getTestBed, ɵgetCleanupHook as getCleanupHook } from '@angular/core/testing';
31
+ import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
32
+ ${providersImport}
33
+ // Same as https://github.com/angular/angular/blob/05a03d3f975771bb59c7eefd37c01fa127ee2229/packages/core/testing/srcs/test_hooks.ts#L21-L29
34
+ beforeEach(getCleanupHook(false));
35
+ afterEach(getCleanupHook(true));
36
+ @NgModule({
37
+ providers,
38
+ })
39
+ export class TestModule {}
40
+ getTestBed().initTestEnvironment([BrowserTestingModule, TestModule], platformBrowserTesting(), {
41
+ errorOnUnknownElements: true,
42
+ errorOnUnknownProperties: true,
43
+ });
44
+ `;
45
+ }
46
+ async function getVitestBuildOptions(options, baseBuildOptions) {
47
+ const { workspaceRoot, projectSourceRoot, include, exclude, watch, tsConfig, providersFile } = options;
48
+ // Find test files
49
+ const testFiles = await (0, test_discovery_1.findTests)(include, exclude, workspaceRoot, projectSourceRoot);
50
+ if (testFiles.length === 0) {
51
+ throw new Error('No tests found matching the following patterns:\n' +
52
+ `- Included: ${include.join(', ')}\n` +
53
+ (exclude.length ? `- Excluded: ${exclude.join(', ')}\n` : '') +
54
+ `\nPlease check the 'test' target configuration in your project's 'angular.json' file.`);
55
+ }
56
+ const entryPoints = (0, test_discovery_1.getTestEntrypoints)(testFiles, { projectSourceRoot, workspaceRoot });
57
+ entryPoints.set('init-testbed', 'angular:test-bed-init');
58
+ const buildOptions = {
59
+ ...baseBuildOptions,
60
+ watch,
61
+ incrementalResults: watch,
62
+ index: false,
63
+ browser: undefined,
64
+ server: undefined,
65
+ outputMode: undefined,
66
+ localize: false,
67
+ budgets: [],
68
+ serviceWorker: false,
69
+ appShell: false,
70
+ ssr: false,
71
+ prerender: false,
72
+ sourceMap: { scripts: true, vendor: false, styles: false },
73
+ outputHashing: schema_1.OutputHashing.None,
74
+ optimization: false,
75
+ tsConfig,
76
+ entryPoints,
77
+ externalDependencies: ['vitest', '@vitest/browser/context'],
78
+ };
79
+ buildOptions.polyfills = (0, options_1.injectTestingPolyfills)(buildOptions.polyfills);
80
+ const testBedInitContents = createTestBedInitVirtualFile(providersFile, projectSourceRoot);
81
+ return {
82
+ buildOptions,
83
+ virtualFiles: {
84
+ 'angular:test-bed-init': testBedInitContents,
85
+ },
86
+ };
87
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import type { BuilderOutput } from '@angular-devkit/architect';
9
+ import type { FullResult, IncrementalResult } from '../../../application/results';
10
+ import { NormalizedUnitTestBuilderOptions } from '../../options';
11
+ import type { TestExecutor } from '../api';
12
+ export declare class VitestExecutor implements TestExecutor {
13
+ private vitest;
14
+ private readonly projectName;
15
+ private readonly options;
16
+ private readonly outputPath;
17
+ private latestBuildResult;
18
+ constructor(projectName: string, options: NormalizedUnitTestBuilderOptions);
19
+ execute(buildResult: FullResult | IncrementalResult): AsyncIterable<BuilderOutput>;
20
+ [Symbol.asyncDispose](): Promise<void>;
21
+ private initializeVitest;
22
+ }
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.VitestExecutor = void 0;
14
+ const node_assert_1 = __importDefault(require("node:assert"));
15
+ const node_crypto_1 = require("node:crypto");
16
+ const node_path_1 = __importDefault(require("node:path"));
17
+ const error_1 = require("../../../../utils/error");
18
+ const load_esm_1 = require("../../../../utils/load-esm");
19
+ const path_1 = require("../../../../utils/path");
20
+ const application_builder_1 = require("../../../karma/application_builder");
21
+ const browser_provider_1 = require("./browser-provider");
22
+ class VitestExecutor {
23
+ vitest;
24
+ projectName;
25
+ options;
26
+ outputPath;
27
+ latestBuildResult;
28
+ constructor(projectName, options) {
29
+ this.projectName = projectName;
30
+ this.options = options;
31
+ this.outputPath = (0, path_1.toPosixPath)(node_path_1.default.join(options.workspaceRoot, generateOutputPath()));
32
+ }
33
+ async *execute(buildResult) {
34
+ await (0, application_builder_1.writeTestFiles)(buildResult.files, this.outputPath);
35
+ this.latestBuildResult = buildResult;
36
+ this.vitest ??= await this.initializeVitest();
37
+ // Check if all the tests pass to calculate the result
38
+ const testModules = this.vitest.state.getTestModules();
39
+ yield { success: testModules.every((testModule) => testModule.ok()) };
40
+ }
41
+ async [Symbol.asyncDispose]() {
42
+ await this.vitest?.close();
43
+ }
44
+ async initializeVitest() {
45
+ const { codeCoverage, reporters, watch, workspaceRoot, setupFiles, browsers, debug } = this.options;
46
+ const { outputPath, projectName, latestBuildResult } = this;
47
+ let vitestNodeModule;
48
+ try {
49
+ vitestNodeModule = await (0, load_esm_1.loadEsmModule)('vitest/node');
50
+ }
51
+ catch (error) {
52
+ (0, error_1.assertIsError)(error);
53
+ if (error.code !== 'ERR_MODULE_NOT_FOUND') {
54
+ throw error;
55
+ }
56
+ throw new Error('The `vitest` package was not found. Please install the package and rerun the test command.');
57
+ }
58
+ const { startVitest } = vitestNodeModule;
59
+ // Setup vitest browser options if configured
60
+ const browserOptions = (0, browser_provider_1.setupBrowserConfiguration)(browsers, debug, this.options.projectSourceRoot);
61
+ if (browserOptions.errors?.length) {
62
+ throw new Error(browserOptions.errors.join('\n'));
63
+ }
64
+ (0, node_assert_1.default)(latestBuildResult, 'buildResult must be available before initializing vitest');
65
+ // Add setup file entries for TestBed initialization and project polyfills
66
+ const testSetupFiles = ['init-testbed.js', ...setupFiles];
67
+ // TODO: Provide additional result metadata to avoid needing to extract based on filename
68
+ const polyfillsFile = Object.keys(latestBuildResult.files).find((f) => f === 'polyfills.js');
69
+ if (polyfillsFile) {
70
+ testSetupFiles.unshift(polyfillsFile);
71
+ }
72
+ const debugOptions = debug
73
+ ? {
74
+ inspectBrk: true,
75
+ isolate: false,
76
+ fileParallelism: false,
77
+ }
78
+ : {};
79
+ return startVitest('test', undefined /* cliFilters */, {
80
+ // Disable configuration file resolution/loading
81
+ config: false,
82
+ root: workspaceRoot,
83
+ project: ['base', projectName],
84
+ name: 'base',
85
+ include: [],
86
+ reporters: reporters ?? ['default'],
87
+ watch,
88
+ coverage: generateCoverageOption(codeCoverage, workspaceRoot, this.outputPath),
89
+ ...debugOptions,
90
+ }, {
91
+ plugins: [
92
+ {
93
+ name: 'angular:project-init',
94
+ async configureVitest(context) {
95
+ // Create a subproject that can be configured with plugins for browser mode.
96
+ // Plugins defined directly in the vite overrides will not be present in the
97
+ // browser specific Vite instance.
98
+ const [project] = await context.injectTestProjects({
99
+ test: {
100
+ name: projectName,
101
+ root: outputPath,
102
+ globals: true,
103
+ setupFiles: testSetupFiles,
104
+ // Use `jsdom` if no browsers are explicitly configured.
105
+ // `node` is effectively no "environment" and the default.
106
+ environment: browserOptions.browser ? 'node' : 'jsdom',
107
+ browser: browserOptions.browser,
108
+ },
109
+ plugins: [
110
+ {
111
+ name: 'angular:html-index',
112
+ transformIndexHtml: () => {
113
+ (0, node_assert_1.default)(latestBuildResult, 'buildResult must be available for HTML index transformation.');
114
+ // Add all global stylesheets
115
+ const styleFiles = Object.entries(latestBuildResult.files).filter(([file]) => file === 'styles.css');
116
+ return styleFiles.map(([href]) => ({
117
+ tag: 'link',
118
+ attrs: { href, rel: 'stylesheet' },
119
+ injectTo: 'head',
120
+ }));
121
+ },
122
+ },
123
+ ],
124
+ });
125
+ // Adjust coverage excludes to not include the otherwise automatically inserted included unit tests.
126
+ // Vite does this as a convenience but is problematic for the bundling strategy employed by the
127
+ // builder's test setup. To workaround this, the excludes are adjusted here to only automatically
128
+ // exclude the TypeScript source test files.
129
+ project.config.coverage.exclude = [
130
+ ...(codeCoverage?.exclude ?? []),
131
+ '**/*.{test,spec}.?(c|m)ts',
132
+ ];
133
+ },
134
+ },
135
+ ],
136
+ });
137
+ }
138
+ }
139
+ exports.VitestExecutor = VitestExecutor;
140
+ function generateOutputPath() {
141
+ const datePrefix = new Date().toISOString().replaceAll(/[-:.]/g, '');
142
+ const uuidSuffix = (0, node_crypto_1.randomUUID)().slice(0, 8);
143
+ return node_path_1.default.join('dist', 'test-out', `${datePrefix}-${uuidSuffix}`);
144
+ }
145
+ function generateCoverageOption(codeCoverage, workspaceRoot, outputPath) {
146
+ if (!codeCoverage) {
147
+ return {
148
+ enabled: false,
149
+ };
150
+ }
151
+ return {
152
+ enabled: true,
153
+ excludeAfterRemap: true,
154
+ include: [`${(0, path_1.toPosixPath)(node_path_1.default.relative(workspaceRoot, outputPath))}/**`],
155
+ // Special handling for `reporter` due to an undefined value causing upstream failures
156
+ ...(codeCoverage.reporters
157
+ ? { reporter: codeCoverage.reporters }
158
+ : {}),
159
+ };
160
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ import type { TestRunner } from '../api';
9
+ /**
10
+ * A declarative definition of the Vitest test runner.
11
+ */
12
+ declare const VitestTestRunner: TestRunner;
13
+ export default VitestTestRunner;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ const node_assert_1 = __importDefault(require("node:assert"));
14
+ const build_options_1 = require("./build-options");
15
+ const executor_1 = require("./executor");
16
+ /**
17
+ * A declarative definition of the Vitest test runner.
18
+ */
19
+ const VitestTestRunner = {
20
+ name: 'vitest',
21
+ getBuildOptions(options, baseBuildOptions) {
22
+ return (0, build_options_1.getVitestBuildOptions)(options, baseBuildOptions);
23
+ },
24
+ async createExecutor(context, options) {
25
+ const projectName = context.target?.project;
26
+ (0, node_assert_1.default)(projectName, 'The builder requires a target.');
27
+ return new executor_1.VitestExecutor(projectName, options);
28
+ },
29
+ };
30
+ exports.default = VitestTestRunner;
@@ -43,6 +43,10 @@ export type Schema = {
43
43
  * instead.
44
44
  */
45
45
  include?: string[];
46
+ /**
47
+ * Log progress to the console while building. Defaults to the build target's progress value.
48
+ */
49
+ progress?: boolean;
46
50
  /**
47
51
  * TypeScript file that exports an array of Angular providers to use during test execution.
48
52
  * The array must be a default export.
@@ -106,6 +106,10 @@
106
106
  "type": "string"
107
107
  },
108
108
  "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."
109
+ },
110
+ "progress": {
111
+ "type": "boolean",
112
+ "description": "Log progress to the console while building. Defaults to the build target's progress value."
109
113
  }
110
114
  },
111
115
  "additionalProperties": false,
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.dev/license
7
+ */
8
+ export { findTests, getTestEntrypoints } from '../karma/find-tests';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.getTestEntrypoints = exports.findTests = void 0;
11
+ // TODO: This should eventually contain the implementations for these
12
+ var find_tests_1 = require("../karma/find-tests");
13
+ Object.defineProperty(exports, "findTests", { enumerable: true, get: function () { return find_tests_1.findTests; } });
14
+ Object.defineProperty(exports, "getTestEntrypoints", { enumerable: true, get: function () { return find_tests_1.getTestEntrypoints; } });
package/src/private.d.ts CHANGED
@@ -17,7 +17,7 @@ import { BundleStylesheetOptions } from './tools/esbuild/stylesheets/bundle-opti
17
17
  export { buildApplicationInternal } from './builders/application';
18
18
  export type { ApplicationBuilderInternalOptions } from './builders/application/options';
19
19
  export { type Result, type ResultFile, ResultKind } from './builders/application/results';
20
- export { serveWithVite } from './builders/dev-server/vite-server';
20
+ export { serveWithVite } from './builders/dev-server/vite';
21
21
  export * from './tools/babel/plugins';
22
22
  export type { ExternalResultMetadata } from './tools/esbuild/bundler-execution-result';
23
23
  export { emitFilesToDisk } from './tools/esbuild/utils';
package/src/private.js CHANGED
@@ -38,8 +38,8 @@ var application_1 = require("./builders/application");
38
38
  Object.defineProperty(exports, "buildApplicationInternal", { enumerable: true, get: function () { return application_1.buildApplicationInternal; } });
39
39
  var results_1 = require("./builders/application/results");
40
40
  Object.defineProperty(exports, "ResultKind", { enumerable: true, get: function () { return results_1.ResultKind; } });
41
- var vite_server_1 = require("./builders/dev-server/vite-server");
42
- Object.defineProperty(exports, "serveWithVite", { enumerable: true, get: function () { return vite_server_1.serveWithVite; } });
41
+ var vite_1 = require("./builders/dev-server/vite");
42
+ Object.defineProperty(exports, "serveWithVite", { enumerable: true, get: function () { return vite_1.serveWithVite; } });
43
43
  // Tools
44
44
  __exportStar(require("./tools/babel/plugins"), exports);
45
45
  var utils_1 = require("./tools/esbuild/utils");