@angular/build 21.0.0-next.2 → 21.0.0-next.4
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.
- package/package.json +14 -14
- package/src/builders/application/index.js +2 -1
- package/src/builders/application/options.d.ts +4 -1
- package/src/builders/karma/application_builder.d.ts +0 -2
- package/src/builders/karma/application_builder.js +39 -351
- package/src/builders/karma/assets-middleware.d.ts +26 -0
- package/src/builders/karma/assets-middleware.js +65 -0
- package/src/builders/karma/coverage.d.ts +9 -0
- package/src/builders/karma/coverage.js +31 -0
- package/src/builders/karma/find-tests.d.ts +2 -1
- package/src/builders/karma/find-tests.js +6 -2
- package/src/builders/karma/karma-config.d.ts +11 -0
- package/src/builders/karma/karma-config.js +79 -0
- package/src/builders/karma/polyfills-plugin.d.ts +13 -0
- package/src/builders/karma/polyfills-plugin.js +74 -0
- package/src/builders/karma/progress-reporter.d.ts +17 -0
- package/src/builders/karma/progress-reporter.js +73 -0
- package/src/builders/karma/utils.d.ts +17 -0
- package/src/builders/karma/utils.js +66 -0
- package/src/builders/unit-test/builder.js +140 -44
- package/src/builders/unit-test/options.d.ts +5 -2
- package/src/builders/unit-test/options.js +12 -6
- package/src/builders/unit-test/runners/api.d.ts +19 -1
- package/src/builders/unit-test/runners/dependency-checker.d.ts +43 -0
- package/src/builders/unit-test/runners/dependency-checker.js +82 -0
- package/src/builders/unit-test/runners/karma/executor.js +26 -2
- package/src/builders/unit-test/runners/karma/index.js +17 -0
- package/src/builders/unit-test/runners/vitest/browser-provider.d.ts +3 -2
- package/src/builders/unit-test/runners/vitest/build-options.js +7 -2
- package/src/builders/unit-test/runners/vitest/executor.d.ts +5 -4
- package/src/builders/unit-test/runners/vitest/executor.js +80 -101
- package/src/builders/unit-test/runners/vitest/index.js +19 -2
- package/src/builders/unit-test/runners/vitest/plugins.d.ts +23 -0
- package/src/builders/unit-test/runners/vitest/plugins.js +131 -0
- package/src/builders/unit-test/schema.d.ts +54 -30
- package/src/builders/unit-test/schema.js +1 -1
- package/src/builders/unit-test/schema.json +66 -19
- package/src/tools/esbuild/stylesheets/bundle-options.d.ts +4 -1
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +4 -1
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.js +6 -3
- package/src/tools/vite/middlewares/assets-middleware.d.ts +2 -0
- package/src/tools/vite/middlewares/assets-middleware.js +31 -0
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/postcss-configuration.d.ts +4 -1
- package/src/utils/postcss-configuration.js +2 -2
- package/src/utils/server-rendering/load-esm-from-memory.d.ts +2 -1
- package/src/utils/supported-browsers.js +7 -3
- package/src/utils/test-files.d.ts +17 -0
- package/src/utils/test-files.js +82 -0
- package/.browserslistrc +0 -7
- package/src/typings.d.ts +0 -19
|
@@ -12,73 +12,96 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.VitestExecutor = void 0;
|
|
14
14
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
15
|
-
const node_crypto_1 = require("node:crypto");
|
|
16
|
-
const node_fs_1 = require("node:fs");
|
|
17
|
-
const promises_1 = require("node:fs/promises");
|
|
18
15
|
const node_path_1 = __importDefault(require("node:path"));
|
|
19
16
|
const error_1 = require("../../../../utils/error");
|
|
20
17
|
const load_esm_1 = require("../../../../utils/load-esm");
|
|
21
18
|
const path_1 = require("../../../../utils/path");
|
|
22
19
|
const results_1 = require("../../../application/results");
|
|
23
|
-
const application_builder_1 = require("../../../karma/application_builder");
|
|
24
20
|
const browser_provider_1 = require("./browser-provider");
|
|
21
|
+
const plugins_1 = require("./plugins");
|
|
25
22
|
class VitestExecutor {
|
|
26
23
|
vitest;
|
|
27
24
|
projectName;
|
|
28
25
|
options;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
constructor(projectName, options) {
|
|
26
|
+
buildResultFiles = new Map();
|
|
27
|
+
// This is a reverse map of the entry points created in `build-options.ts`.
|
|
28
|
+
// It is used by the in-memory provider plugin to map the requested test file
|
|
29
|
+
// path back to its bundled output path.
|
|
30
|
+
// Example: `Map<'/path/to/src/app.spec.ts', 'spec-src-app-spec'>`
|
|
31
|
+
testFileToEntryPoint = new Map();
|
|
32
|
+
entryPointToTestFile = new Map();
|
|
33
|
+
constructor(projectName, options, testEntryPointMappings) {
|
|
37
34
|
this.projectName = projectName;
|
|
38
35
|
this.options = options;
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
if (testEntryPointMappings) {
|
|
37
|
+
for (const [entryPoint, testFile] of testEntryPointMappings) {
|
|
38
|
+
this.testFileToEntryPoint.set(testFile, entryPoint);
|
|
39
|
+
this.entryPointToTestFile.set(entryPoint + '.js', testFile);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
41
42
|
}
|
|
42
43
|
async *execute(buildResult) {
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
if (buildResult.kind === results_1.ResultKind.Full) {
|
|
45
|
+
this.buildResultFiles.clear();
|
|
46
|
+
for (const [path, file] of Object.entries(buildResult.files)) {
|
|
47
|
+
this.buildResultFiles.set(path, file);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
for (const file of buildResult.removed) {
|
|
52
|
+
this.buildResultFiles.delete(file.path);
|
|
53
|
+
}
|
|
54
|
+
for (const [path, file] of Object.entries(buildResult.files)) {
|
|
55
|
+
this.buildResultFiles.set(path, file);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
45
58
|
// Initialize Vitest if not already present.
|
|
46
59
|
this.vitest ??= await this.initializeVitest();
|
|
47
60
|
const vitest = this.vitest;
|
|
48
61
|
let testResults;
|
|
49
62
|
if (buildResult.kind === results_1.ResultKind.Incremental) {
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
// To rerun tests, Vitest needs the original test file paths, not the output paths.
|
|
64
|
+
const modifiedSourceFiles = new Set();
|
|
65
|
+
for (const modifiedFile of buildResult.modified) {
|
|
66
|
+
// The `modified` files in the build result are the output paths.
|
|
67
|
+
// We need to find the original source file path to pass to Vitest.
|
|
68
|
+
const source = this.entryPointToTestFile.get(modifiedFile);
|
|
69
|
+
if (source) {
|
|
70
|
+
modifiedSourceFiles.add(source);
|
|
71
|
+
}
|
|
72
|
+
vitest.invalidateFile((0, path_1.toPosixPath)(node_path_1.default.join(this.options.workspaceRoot, modifiedFile)));
|
|
60
73
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
const specsToRerun = [];
|
|
75
|
+
for (const file of modifiedSourceFiles) {
|
|
76
|
+
vitest.invalidateFile(file);
|
|
77
|
+
const specs = vitest.getModuleSpecifications(file);
|
|
78
|
+
if (specs) {
|
|
79
|
+
specsToRerun.push(...specs);
|
|
67
80
|
}
|
|
68
81
|
}
|
|
82
|
+
if (specsToRerun.length > 0) {
|
|
83
|
+
testResults = await vitest.rerunTestSpecifications(specsToRerun);
|
|
84
|
+
}
|
|
69
85
|
}
|
|
70
86
|
// Check if all the tests pass to calculate the result
|
|
71
|
-
const testModules = testResults?.testModules;
|
|
72
|
-
yield { success: testModules
|
|
87
|
+
const testModules = testResults?.testModules ?? this.vitest.state.getTestModules();
|
|
88
|
+
yield { success: testModules.every((testModule) => testModule.ok()) };
|
|
73
89
|
}
|
|
74
90
|
async [Symbol.asyncDispose]() {
|
|
75
|
-
process.off('SIGINT', this.sigintListener);
|
|
76
91
|
await this.vitest?.close();
|
|
77
|
-
|
|
92
|
+
}
|
|
93
|
+
prepareSetupFiles() {
|
|
94
|
+
const { setupFiles } = this.options;
|
|
95
|
+
// Add setup file entries for TestBed initialization and project polyfills
|
|
96
|
+
const testSetupFiles = ['init-testbed.js', ...setupFiles];
|
|
97
|
+
// TODO: Provide additional result metadata to avoid needing to extract based on filename
|
|
98
|
+
if (this.buildResultFiles.has('polyfills.js')) {
|
|
99
|
+
testSetupFiles.unshift('polyfills.js');
|
|
100
|
+
}
|
|
101
|
+
return testSetupFiles;
|
|
78
102
|
}
|
|
79
103
|
async initializeVitest() {
|
|
80
|
-
const { codeCoverage, reporters,
|
|
81
|
-
const { outputPath, projectName, latestBuildResult } = this;
|
|
104
|
+
const { codeCoverage, reporters, outputFile, workspaceRoot, browsers, debug, watch } = this.options;
|
|
82
105
|
let vitestNodeModule;
|
|
83
106
|
try {
|
|
84
107
|
vitestNodeModule = await (0, load_esm_1.loadEsmModule)('vitest/node');
|
|
@@ -96,14 +119,17 @@ class VitestExecutor {
|
|
|
96
119
|
if (browserOptions.errors?.length) {
|
|
97
120
|
throw new Error(browserOptions.errors.join('\n'));
|
|
98
121
|
}
|
|
99
|
-
(0, node_assert_1.default)(
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
122
|
+
(0, node_assert_1.default)(this.buildResultFiles.size > 0, 'buildResult must be available before initializing vitest');
|
|
123
|
+
const testSetupFiles = this.prepareSetupFiles();
|
|
124
|
+
const plugins = (0, plugins_1.createVitestPlugins)(this.options, testSetupFiles, browserOptions, {
|
|
125
|
+
workspaceRoot,
|
|
126
|
+
projectSourceRoot: this.options.projectSourceRoot,
|
|
127
|
+
projectName: this.projectName,
|
|
128
|
+
include: this.options.include,
|
|
129
|
+
exclude: this.options.exclude,
|
|
130
|
+
buildResultFiles: this.buildResultFiles,
|
|
131
|
+
testFileToEntryPoint: this.testFileToEntryPoint,
|
|
132
|
+
});
|
|
107
133
|
const debugOptions = debug
|
|
108
134
|
? {
|
|
109
135
|
inspectBrk: true,
|
|
@@ -115,12 +141,14 @@ class VitestExecutor {
|
|
|
115
141
|
// Disable configuration file resolution/loading
|
|
116
142
|
config: false,
|
|
117
143
|
root: workspaceRoot,
|
|
118
|
-
project: ['base', projectName],
|
|
144
|
+
project: ['base', this.projectName],
|
|
119
145
|
name: 'base',
|
|
120
146
|
include: [],
|
|
147
|
+
testNamePattern: this.options.filter,
|
|
121
148
|
reporters: reporters ?? ['default'],
|
|
149
|
+
outputFile,
|
|
122
150
|
watch,
|
|
123
|
-
coverage: generateCoverageOption(codeCoverage
|
|
151
|
+
coverage: generateCoverageOption(codeCoverage),
|
|
124
152
|
...debugOptions,
|
|
125
153
|
}, {
|
|
126
154
|
server: {
|
|
@@ -128,61 +156,12 @@ class VitestExecutor {
|
|
|
128
156
|
// be enabled as it controls other internal behavior related to rerunning tests.
|
|
129
157
|
watch: null,
|
|
130
158
|
},
|
|
131
|
-
plugins
|
|
132
|
-
{
|
|
133
|
-
name: 'angular:project-init',
|
|
134
|
-
async configureVitest(context) {
|
|
135
|
-
// Create a subproject that can be configured with plugins for browser mode.
|
|
136
|
-
// Plugins defined directly in the vite overrides will not be present in the
|
|
137
|
-
// browser specific Vite instance.
|
|
138
|
-
const [project] = await context.injectTestProjects({
|
|
139
|
-
test: {
|
|
140
|
-
name: projectName,
|
|
141
|
-
root: outputPath,
|
|
142
|
-
globals: true,
|
|
143
|
-
setupFiles: testSetupFiles,
|
|
144
|
-
// Use `jsdom` if no browsers are explicitly configured.
|
|
145
|
-
// `node` is effectively no "environment" and the default.
|
|
146
|
-
environment: browserOptions.browser ? 'node' : 'jsdom',
|
|
147
|
-
browser: browserOptions.browser,
|
|
148
|
-
},
|
|
149
|
-
plugins: [
|
|
150
|
-
{
|
|
151
|
-
name: 'angular:html-index',
|
|
152
|
-
transformIndexHtml: () => {
|
|
153
|
-
(0, node_assert_1.default)(latestBuildResult, 'buildResult must be available for HTML index transformation.');
|
|
154
|
-
// Add all global stylesheets
|
|
155
|
-
const styleFiles = Object.entries(latestBuildResult.files).filter(([file]) => file === 'styles.css');
|
|
156
|
-
return styleFiles.map(([href]) => ({
|
|
157
|
-
tag: 'link',
|
|
158
|
-
attrs: { href, rel: 'stylesheet' },
|
|
159
|
-
injectTo: 'head',
|
|
160
|
-
}));
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
],
|
|
164
|
-
});
|
|
165
|
-
// Adjust coverage excludes to not include the otherwise automatically inserted included unit tests.
|
|
166
|
-
// Vite does this as a convenience but is problematic for the bundling strategy employed by the
|
|
167
|
-
// builder's test setup. To workaround this, the excludes are adjusted here to only automatically
|
|
168
|
-
// exclude the TypeScript source test files.
|
|
169
|
-
project.config.coverage.exclude = [
|
|
170
|
-
...(codeCoverage?.exclude ?? []),
|
|
171
|
-
'**/*.{test,spec}.?(c|m)ts',
|
|
172
|
-
];
|
|
173
|
-
},
|
|
174
|
-
},
|
|
175
|
-
],
|
|
159
|
+
plugins,
|
|
176
160
|
});
|
|
177
161
|
}
|
|
178
162
|
}
|
|
179
163
|
exports.VitestExecutor = VitestExecutor;
|
|
180
|
-
function
|
|
181
|
-
const datePrefix = new Date().toISOString().replaceAll(/[-:.]/g, '');
|
|
182
|
-
const uuidSuffix = (0, node_crypto_1.randomUUID)().slice(0, 8);
|
|
183
|
-
return node_path_1.default.join('dist', 'test-out', `${datePrefix}-${uuidSuffix}`);
|
|
184
|
-
}
|
|
185
|
-
function generateCoverageOption(codeCoverage, workspaceRoot, outputPath) {
|
|
164
|
+
function generateCoverageOption(codeCoverage) {
|
|
186
165
|
if (!codeCoverage) {
|
|
187
166
|
return {
|
|
188
167
|
enabled: false,
|
|
@@ -191,8 +170,8 @@ function generateCoverageOption(codeCoverage, workspaceRoot, outputPath) {
|
|
|
191
170
|
return {
|
|
192
171
|
enabled: true,
|
|
193
172
|
excludeAfterRemap: true,
|
|
194
|
-
|
|
195
|
-
|
|
173
|
+
// Special handling for `exclude`/`reporters` due to an undefined value causing upstream failures
|
|
174
|
+
...(codeCoverage.exclude ? { exclude: codeCoverage.exclude } : {}),
|
|
196
175
|
...(codeCoverage.reporters
|
|
197
176
|
? { reporter: codeCoverage.reporters }
|
|
198
177
|
: {}),
|
|
@@ -11,6 +11,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
14
|
+
const dependency_checker_1 = require("../dependency-checker");
|
|
14
15
|
const build_options_1 = require("./build-options");
|
|
15
16
|
const executor_1 = require("./executor");
|
|
16
17
|
/**
|
|
@@ -18,13 +19,29 @@ const executor_1 = require("./executor");
|
|
|
18
19
|
*/
|
|
19
20
|
const VitestTestRunner = {
|
|
20
21
|
name: 'vitest',
|
|
22
|
+
validateDependencies(options) {
|
|
23
|
+
const checker = new dependency_checker_1.DependencyChecker(options.projectSourceRoot);
|
|
24
|
+
checker.check('vitest');
|
|
25
|
+
if (options.browsers?.length) {
|
|
26
|
+
checker.check('@vitest/browser');
|
|
27
|
+
checker.checkAny(['playwright', 'webdriverio'], 'The "browsers" option requires either "playwright" or "webdriverio" to be installed.');
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// JSDOM is used when no browsers are specified
|
|
31
|
+
checker.check('jsdom');
|
|
32
|
+
}
|
|
33
|
+
if (options.codeCoverage) {
|
|
34
|
+
checker.check('@vitest/coverage-v8');
|
|
35
|
+
}
|
|
36
|
+
checker.report();
|
|
37
|
+
},
|
|
21
38
|
getBuildOptions(options, baseBuildOptions) {
|
|
22
39
|
return (0, build_options_1.getVitestBuildOptions)(options, baseBuildOptions);
|
|
23
40
|
},
|
|
24
|
-
async createExecutor(context, options) {
|
|
41
|
+
async createExecutor(context, options, testEntryPointMappings) {
|
|
25
42
|
const projectName = context.target?.project;
|
|
26
43
|
(0, node_assert_1.default)(projectName, 'The builder requires a target.');
|
|
27
|
-
return new executor_1.VitestExecutor(projectName, options);
|
|
44
|
+
return new executor_1.VitestExecutor(projectName, options, testEntryPointMappings);
|
|
28
45
|
},
|
|
29
46
|
};
|
|
30
47
|
exports.default = VitestTestRunner;
|
|
@@ -0,0 +1,23 @@
|
|
|
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 { VitestPlugin } from 'vitest/node';
|
|
9
|
+
import type { ResultFile } from '../../../application/results';
|
|
10
|
+
import type { NormalizedUnitTestBuilderOptions } from '../../options';
|
|
11
|
+
import type { BrowserConfiguration } from './browser-provider';
|
|
12
|
+
type VitestPlugins = Awaited<ReturnType<typeof VitestPlugin>>;
|
|
13
|
+
interface PluginOptions {
|
|
14
|
+
workspaceRoot: string;
|
|
15
|
+
projectSourceRoot: string;
|
|
16
|
+
projectName: string;
|
|
17
|
+
include?: string[];
|
|
18
|
+
exclude?: string[];
|
|
19
|
+
buildResultFiles: ReadonlyMap<string, ResultFile>;
|
|
20
|
+
testFileToEntryPoint: ReadonlyMap<string, string>;
|
|
21
|
+
}
|
|
22
|
+
export declare function createVitestPlugins(options: NormalizedUnitTestBuilderOptions, testSetupFiles: string[], browserOptions: BrowserConfiguration, pluginOptions: PluginOptions): VitestPlugins;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,131 @@
|
|
|
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.createVitestPlugins = createVitestPlugins;
|
|
14
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
15
|
+
const promises_1 = require("node:fs/promises");
|
|
16
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
17
|
+
const assets_middleware_1 = require("../../../../tools/vite/middlewares/assets-middleware");
|
|
18
|
+
const path_1 = require("../../../../utils/path");
|
|
19
|
+
function createVitestPlugins(options, testSetupFiles, browserOptions, pluginOptions) {
|
|
20
|
+
const { workspaceRoot, projectName, buildResultFiles, testFileToEntryPoint } = pluginOptions;
|
|
21
|
+
return [
|
|
22
|
+
{
|
|
23
|
+
name: 'angular:project-init',
|
|
24
|
+
// Type is incorrect. This allows a Promise<void>.
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
26
|
+
configureVitest: async (context) => {
|
|
27
|
+
// Create a subproject that can be configured with plugins for browser mode.
|
|
28
|
+
// Plugins defined directly in the vite overrides will not be present in the
|
|
29
|
+
// browser specific Vite instance.
|
|
30
|
+
await context.injectTestProjects({
|
|
31
|
+
test: {
|
|
32
|
+
name: projectName,
|
|
33
|
+
root: workspaceRoot,
|
|
34
|
+
globals: true,
|
|
35
|
+
setupFiles: testSetupFiles,
|
|
36
|
+
// Use `jsdom` if no browsers are explicitly configured.
|
|
37
|
+
// `node` is effectively no "environment" and the default.
|
|
38
|
+
environment: browserOptions.browser ? 'node' : 'jsdom',
|
|
39
|
+
browser: browserOptions.browser,
|
|
40
|
+
include: options.include,
|
|
41
|
+
...(options.exclude ? { exclude: options.exclude } : {}),
|
|
42
|
+
},
|
|
43
|
+
plugins: [
|
|
44
|
+
{
|
|
45
|
+
name: 'angular:test-in-memory-provider',
|
|
46
|
+
enforce: 'pre',
|
|
47
|
+
resolveId: (id, importer) => {
|
|
48
|
+
if (importer && (id[0] === '.' || id[0] === '/')) {
|
|
49
|
+
let fullPath;
|
|
50
|
+
if (testFileToEntryPoint.has(importer)) {
|
|
51
|
+
fullPath = (0, path_1.toPosixPath)(node_path_1.default.join(workspaceRoot, id));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
fullPath = (0, path_1.toPosixPath)(node_path_1.default.join(node_path_1.default.dirname(importer), id));
|
|
55
|
+
}
|
|
56
|
+
const relativePath = node_path_1.default.relative(workspaceRoot, fullPath);
|
|
57
|
+
if (buildResultFiles.has((0, path_1.toPosixPath)(relativePath))) {
|
|
58
|
+
return fullPath;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (testFileToEntryPoint.has(id)) {
|
|
62
|
+
return id;
|
|
63
|
+
}
|
|
64
|
+
(0, node_assert_1.default)(buildResultFiles.size > 0, 'buildResult must be available for resolving.');
|
|
65
|
+
const relativePath = node_path_1.default.relative(workspaceRoot, id);
|
|
66
|
+
if (buildResultFiles.has((0, path_1.toPosixPath)(relativePath))) {
|
|
67
|
+
return id;
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
load: async (id) => {
|
|
71
|
+
(0, node_assert_1.default)(buildResultFiles.size > 0, 'buildResult must be available for in-memory loading.');
|
|
72
|
+
// Attempt to load as a source test file.
|
|
73
|
+
const entryPoint = testFileToEntryPoint.get(id);
|
|
74
|
+
let outputPath;
|
|
75
|
+
if (entryPoint) {
|
|
76
|
+
outputPath = entryPoint + '.js';
|
|
77
|
+
// To support coverage exclusion of the actual test file, the virtual
|
|
78
|
+
// test entry point only references the built and bundled intermediate file.
|
|
79
|
+
return {
|
|
80
|
+
code: `import "./${outputPath}";`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
// Attempt to load as a built artifact.
|
|
85
|
+
const relativePath = node_path_1.default.relative(workspaceRoot, id);
|
|
86
|
+
outputPath = (0, path_1.toPosixPath)(relativePath);
|
|
87
|
+
}
|
|
88
|
+
const outputFile = buildResultFiles.get(outputPath);
|
|
89
|
+
if (outputFile) {
|
|
90
|
+
const sourceMapPath = outputPath + '.map';
|
|
91
|
+
const sourceMapFile = buildResultFiles.get(sourceMapPath);
|
|
92
|
+
const code = outputFile.origin === 'memory'
|
|
93
|
+
? Buffer.from(outputFile.contents).toString('utf-8')
|
|
94
|
+
: await (0, promises_1.readFile)(outputFile.inputPath, 'utf-8');
|
|
95
|
+
const map = sourceMapFile
|
|
96
|
+
? sourceMapFile.origin === 'memory'
|
|
97
|
+
? Buffer.from(sourceMapFile.contents).toString('utf-8')
|
|
98
|
+
: await (0, promises_1.readFile)(sourceMapFile.inputPath, 'utf-8')
|
|
99
|
+
: undefined;
|
|
100
|
+
return {
|
|
101
|
+
code,
|
|
102
|
+
map: map ? JSON.parse(map) : undefined,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
configureServer: (server) => {
|
|
107
|
+
server.middlewares.use((0, assets_middleware_1.createBuildAssetsMiddleware)(server.config.base, buildResultFiles));
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'angular:html-index',
|
|
112
|
+
transformIndexHtml: () => {
|
|
113
|
+
// Add all global stylesheets
|
|
114
|
+
if (buildResultFiles.has('styles.css')) {
|
|
115
|
+
return [
|
|
116
|
+
{
|
|
117
|
+
tag: 'link',
|
|
118
|
+
attrs: { href: 'styles.css', rel: 'stylesheet' },
|
|
119
|
+
injectTo: 'head',
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
return [];
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
}
|
|
@@ -3,76 +3,96 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export type Schema = {
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* 'ChromeHeadless') will enable headless mode
|
|
6
|
+
* Specifies the browsers to use for test execution. When not specified, tests are run in a
|
|
7
|
+
* Node.js environment using jsdom. For both Vitest and Karma, browser names ending with
|
|
8
|
+
* 'Headless' (e.g., 'ChromeHeadless') will enable headless mode.
|
|
9
9
|
*/
|
|
10
10
|
browsers?: string[];
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
* can also pass
|
|
14
|
-
* `project:target:production,staging`.
|
|
12
|
+
* Specifies the build target to use for the unit test build in the format
|
|
13
|
+
* `project:target[:configuration]`. You can also pass a comma-separated list of
|
|
14
|
+
* configurations. Example: `project:target:production,staging`.
|
|
15
15
|
*/
|
|
16
16
|
buildTarget: string;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* Enables code coverage reporting for tests.
|
|
19
19
|
*/
|
|
20
20
|
codeCoverage?: boolean;
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
22
|
+
* Specifies glob patterns of files to exclude from the code coverage report.
|
|
23
23
|
*/
|
|
24
24
|
codeCoverageExclude?: string[];
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Specifies the reporters to use for code coverage results. Each reporter can be a string
|
|
27
|
+
* representing its name, or a tuple containing the name and an options object. Built-in
|
|
28
|
+
* reporters include 'html', 'lcov', 'lcovonly', 'text', 'text-summary', 'cobertura',
|
|
29
|
+
* 'json', and 'json-summary'.
|
|
27
30
|
*/
|
|
28
31
|
codeCoverageReporters?: SchemaCodeCoverageReporter[];
|
|
29
32
|
/**
|
|
30
|
-
*
|
|
33
|
+
* Enables debugging mode for tests, allowing the use of the Node Inspector.
|
|
31
34
|
*/
|
|
32
35
|
debug?: boolean;
|
|
33
36
|
/**
|
|
34
|
-
*
|
|
37
|
+
* Dumps build output files to the `.angular/cache` directory for debugging purposes.
|
|
38
|
+
*/
|
|
39
|
+
dumpVirtualFiles?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Specifies glob patterns of files to exclude from testing, relative to the project root.
|
|
35
42
|
*/
|
|
36
43
|
exclude?: string[];
|
|
37
44
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
* Specifies a regular expression pattern to match against test suite and test names. Only
|
|
46
|
+
* tests with a name matching the pattern will be executed. For example, `^App` will run
|
|
47
|
+
* only tests in suites beginning with 'App'.
|
|
48
|
+
*/
|
|
49
|
+
filter?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Specifies glob patterns of files to include for testing, relative to the project root.
|
|
52
|
+
* This option also has special handling for directory paths (includes all `.spec.ts` files
|
|
53
|
+
* within) and file paths (includes the corresponding `.spec` file if one exists).
|
|
44
54
|
*/
|
|
45
55
|
include?: string[];
|
|
46
56
|
/**
|
|
47
|
-
*
|
|
57
|
+
* Specifies a file path for the test report, applying only to the first reporter. To
|
|
58
|
+
* configure output files for multiple reporters, use the tuple format `['reporter-name', {
|
|
59
|
+
* outputFile: '...' }]` within the `reporters` option. When not provided, output is written
|
|
60
|
+
* to the console.
|
|
61
|
+
*/
|
|
62
|
+
outputFile?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Shows build progress information in the console. Defaults to the `progress` setting of
|
|
65
|
+
* the specified `buildTarget`.
|
|
48
66
|
*/
|
|
49
67
|
progress?: boolean;
|
|
50
68
|
/**
|
|
51
|
-
* TypeScript file that
|
|
52
|
-
* The
|
|
69
|
+
* Specifies the path to a TypeScript file that provides an array of Angular providers for
|
|
70
|
+
* the test environment. The file must contain a default export of the provider array.
|
|
53
71
|
*/
|
|
54
72
|
providersFile?: string;
|
|
55
73
|
/**
|
|
56
|
-
*
|
|
74
|
+
* Specifies the reporters to use during test execution. Each reporter can be a string
|
|
75
|
+
* representing its name, or a tuple containing the name and an options object. Built-in
|
|
76
|
+
* reporters include 'default', 'verbose', 'dots', 'json', 'junit', 'tap', 'tap-flat', and
|
|
77
|
+
* 'html'. You can also provide a path to a custom reporter.
|
|
57
78
|
*/
|
|
58
|
-
reporters?:
|
|
79
|
+
reporters?: SchemaReporter[];
|
|
59
80
|
/**
|
|
60
|
-
*
|
|
81
|
+
* Specifies the test runner to use for test execution.
|
|
61
82
|
*/
|
|
62
83
|
runner: Runner;
|
|
63
84
|
/**
|
|
64
|
-
* A list of global setup
|
|
65
|
-
*
|
|
66
|
-
* is also initialized prior to the execution of these files.
|
|
85
|
+
* A list of paths to global setup files that are executed before the test files. The
|
|
86
|
+
* application's polyfills and the Angular TestBed are always initialized before these files.
|
|
67
87
|
*/
|
|
68
88
|
setupFiles?: string[];
|
|
69
89
|
/**
|
|
70
|
-
* The
|
|
90
|
+
* The path to the TypeScript configuration file, relative to the workspace root.
|
|
71
91
|
*/
|
|
72
92
|
tsConfig: string;
|
|
73
93
|
/**
|
|
74
|
-
*
|
|
75
|
-
* otherwise.
|
|
94
|
+
* Enables watch mode, which re-runs tests when source files change. Defaults to `true` in
|
|
95
|
+
* TTY environments and `false` otherwise.
|
|
76
96
|
*/
|
|
77
97
|
watch?: boolean;
|
|
78
98
|
};
|
|
@@ -90,8 +110,12 @@ export declare enum CoverageReporters {
|
|
|
90
110
|
Text = "text",
|
|
91
111
|
TextSummary = "text-summary"
|
|
92
112
|
}
|
|
113
|
+
export type SchemaReporter = ReporterReporter[] | string;
|
|
114
|
+
export type ReporterReporter = {
|
|
115
|
+
[key: string]: any;
|
|
116
|
+
} | string;
|
|
93
117
|
/**
|
|
94
|
-
*
|
|
118
|
+
* Specifies the test runner to use for test execution.
|
|
95
119
|
*/
|
|
96
120
|
export declare enum Runner {
|
|
97
121
|
Karma = "karma",
|
|
@@ -15,7 +15,7 @@ var CoverageReporters;
|
|
|
15
15
|
CoverageReporters["TextSummary"] = "text-summary";
|
|
16
16
|
})(CoverageReporters || (exports.CoverageReporters = CoverageReporters = {}));
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* Specifies the test runner to use for test execution.
|
|
19
19
|
*/
|
|
20
20
|
var Runner;
|
|
21
21
|
(function (Runner) {
|