@angular/build 21.0.0-next.4 → 21.0.0-next.6
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 +8 -8
- package/src/builders/karma/application_builder.js +5 -1
- package/src/builders/karma/coverage.js +1 -1
- package/src/builders/karma/find-tests.d.ts +1 -9
- package/src/builders/karma/find-tests.js +6 -106
- package/src/builders/unit-test/builder.js +20 -2
- package/src/builders/unit-test/options.d.ts +16 -2
- package/src/builders/unit-test/options.js +37 -4
- package/src/builders/unit-test/runners/karma/executor.js +26 -3
- package/src/builders/unit-test/runners/karma/index.js +1 -1
- package/src/builders/unit-test/runners/vitest/browser-provider.d.ts +4 -1
- package/src/builders/unit-test/runners/vitest/browser-provider.js +6 -2
- package/src/builders/unit-test/runners/vitest/build-options.js +6 -6
- package/src/builders/unit-test/runners/vitest/executor.js +30 -8
- package/src/builders/unit-test/runners/vitest/index.js +1 -1
- package/src/builders/unit-test/schema.d.ts +93 -13
- package/src/builders/unit-test/schema.js +12 -12
- package/src/builders/unit-test/schema.json +126 -33
- package/src/builders/unit-test/test-discovery.d.ts +25 -1
- package/src/builders/unit-test/test-discovery.js +194 -5
- package/src/tools/angular/transformers/jit-bootstrap-transformer.js +1 -1
- package/src/tools/angular/transformers/jit-resource-transformer.js +1 -1
- package/src/tools/babel/plugins/pure-toplevel-functions.d.ts +0 -1
- package/src/tools/babel/plugins/pure-toplevel-functions.js +21 -5
- package/src/tools/esbuild/angular/compiler-plugin.js +38 -14
- package/src/tools/esbuild/javascript-transformer-worker.js +2 -8
- package/src/tools/esbuild/stylesheets/less-language.js +2 -26
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.js +2 -1
- package/src/utils/normalize-cache.js +1 -1
- package/src/utils/server-rendering/utils.d.ts +1 -1
- package/src/utils/service-worker.d.ts +1 -1
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* Unit testing options for Angular applications.
|
|
3
3
|
*/
|
|
4
4
|
export type Schema = {
|
|
5
|
+
/**
|
|
6
|
+
* Specifies the browser viewport dimensions for browser-based tests in the format
|
|
7
|
+
* `widthxheight`.
|
|
8
|
+
*/
|
|
9
|
+
browserViewport?: string;
|
|
5
10
|
/**
|
|
6
11
|
* Specifies the browsers to use for test execution. When not specified, tests are run in a
|
|
7
12
|
* Node.js environment using jsdom. For both Vitest and Karma, browser names ending with
|
|
@@ -10,25 +15,45 @@ export type Schema = {
|
|
|
10
15
|
browsers?: string[];
|
|
11
16
|
/**
|
|
12
17
|
* Specifies the build target to use for the unit test build in the format
|
|
13
|
-
* `project:target[:configuration]`.
|
|
18
|
+
* `project:target[:configuration]`. This defaults to the `build` target of the current
|
|
19
|
+
* project with the `development` configuration. You can also pass a comma-separated list of
|
|
14
20
|
* configurations. Example: `project:target:production,staging`.
|
|
15
21
|
*/
|
|
16
|
-
buildTarget
|
|
22
|
+
buildTarget?: string;
|
|
17
23
|
/**
|
|
18
|
-
* Enables
|
|
24
|
+
* Enables coverage reporting for tests.
|
|
19
25
|
*/
|
|
20
|
-
|
|
26
|
+
coverage?: boolean;
|
|
21
27
|
/**
|
|
22
|
-
*
|
|
28
|
+
* Includes all files that match the `coverageInclude` pattern in the coverage report, not
|
|
29
|
+
* just those touched by tests.
|
|
23
30
|
*/
|
|
24
|
-
|
|
31
|
+
coverageAll?: boolean;
|
|
25
32
|
/**
|
|
26
|
-
* Specifies
|
|
33
|
+
* Specifies glob patterns of files to exclude from the coverage report.
|
|
34
|
+
*/
|
|
35
|
+
coverageExclude?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Specifies glob patterns of files to include in the coverage report.
|
|
38
|
+
*/
|
|
39
|
+
coverageInclude?: string[];
|
|
40
|
+
/**
|
|
41
|
+
* Specifies the reporters to use for coverage results. Each reporter can be a string
|
|
27
42
|
* representing its name, or a tuple containing the name and an options object. Built-in
|
|
28
43
|
* reporters include 'html', 'lcov', 'lcovonly', 'text', 'text-summary', 'cobertura',
|
|
29
44
|
* 'json', and 'json-summary'.
|
|
30
45
|
*/
|
|
31
|
-
|
|
46
|
+
coverageReporters?: SchemaCoverageReporter[];
|
|
47
|
+
/**
|
|
48
|
+
* Specifies minimum coverage thresholds that must be met. If thresholds are not met, the
|
|
49
|
+
* builder will exit with an error.
|
|
50
|
+
*/
|
|
51
|
+
coverageThresholds?: CoverageThresholds;
|
|
52
|
+
/**
|
|
53
|
+
* Specifies coverage watermarks for the HTML reporter. These determine the color coding for
|
|
54
|
+
* high, medium, and low coverage.
|
|
55
|
+
*/
|
|
56
|
+
coverageWatermarks?: CoverageWatermarks;
|
|
32
57
|
/**
|
|
33
58
|
* Enables debugging mode for tests, allowing the use of the Node Inspector.
|
|
34
59
|
*/
|
|
@@ -53,6 +78,11 @@ export type Schema = {
|
|
|
53
78
|
* within) and file paths (includes the corresponding `.spec` file if one exists).
|
|
54
79
|
*/
|
|
55
80
|
include?: string[];
|
|
81
|
+
/**
|
|
82
|
+
* Lists all discovered test files and exits the process without building or executing the
|
|
83
|
+
* tests.
|
|
84
|
+
*/
|
|
85
|
+
listTests?: boolean;
|
|
56
86
|
/**
|
|
57
87
|
* Specifies a file path for the test report, applying only to the first reporter. To
|
|
58
88
|
* configure output files for multiple reporters, use the tuple format `['reporter-name', {
|
|
@@ -87,20 +117,22 @@ export type Schema = {
|
|
|
87
117
|
*/
|
|
88
118
|
setupFiles?: string[];
|
|
89
119
|
/**
|
|
90
|
-
* The path to the TypeScript configuration file, relative to the workspace root.
|
|
120
|
+
* The path to the TypeScript configuration file, relative to the workspace root. Defaults
|
|
121
|
+
* to `tsconfig.spec.json` in the project root if it exists. If not specified and the
|
|
122
|
+
* default does not exist, the `tsConfig` from the specified `buildTarget` will be used.
|
|
91
123
|
*/
|
|
92
|
-
tsConfig
|
|
124
|
+
tsConfig?: string;
|
|
93
125
|
/**
|
|
94
126
|
* Enables watch mode, which re-runs tests when source files change. Defaults to `true` in
|
|
95
127
|
* TTY environments and `false` otherwise.
|
|
96
128
|
*/
|
|
97
129
|
watch?: boolean;
|
|
98
130
|
};
|
|
99
|
-
export type
|
|
100
|
-
export type
|
|
131
|
+
export type SchemaCoverageReporter = CoverageReporterCoverageReporterUnion[] | CoverageReporterEnum;
|
|
132
|
+
export type CoverageReporterCoverageReporterUnion = CoverageReporterEnum | {
|
|
101
133
|
[key: string]: any;
|
|
102
134
|
};
|
|
103
|
-
export declare enum
|
|
135
|
+
export declare enum CoverageReporterEnum {
|
|
104
136
|
Cobertura = "cobertura",
|
|
105
137
|
Html = "html",
|
|
106
138
|
Json = "json",
|
|
@@ -110,6 +142,54 @@ export declare enum CoverageReporters {
|
|
|
110
142
|
Text = "text",
|
|
111
143
|
TextSummary = "text-summary"
|
|
112
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Specifies minimum coverage thresholds that must be met. If thresholds are not met, the
|
|
147
|
+
* builder will exit with an error.
|
|
148
|
+
*/
|
|
149
|
+
export type CoverageThresholds = {
|
|
150
|
+
/**
|
|
151
|
+
* Minimum percentage of branches covered.
|
|
152
|
+
*/
|
|
153
|
+
branches?: number;
|
|
154
|
+
/**
|
|
155
|
+
* Minimum percentage of functions covered.
|
|
156
|
+
*/
|
|
157
|
+
functions?: number;
|
|
158
|
+
/**
|
|
159
|
+
* Minimum percentage of lines covered.
|
|
160
|
+
*/
|
|
161
|
+
lines?: number;
|
|
162
|
+
/**
|
|
163
|
+
* When true, thresholds are enforced for each file individually.
|
|
164
|
+
*/
|
|
165
|
+
perFile?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Minimum percentage of statements covered.
|
|
168
|
+
*/
|
|
169
|
+
statements?: number;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Specifies coverage watermarks for the HTML reporter. These determine the color coding for
|
|
173
|
+
* high, medium, and low coverage.
|
|
174
|
+
*/
|
|
175
|
+
export type CoverageWatermarks = {
|
|
176
|
+
/**
|
|
177
|
+
* The high and low watermarks for branches coverage. `[low, high]`
|
|
178
|
+
*/
|
|
179
|
+
branches?: number[];
|
|
180
|
+
/**
|
|
181
|
+
* The high and low watermarks for functions coverage. `[low, high]`
|
|
182
|
+
*/
|
|
183
|
+
functions?: number[];
|
|
184
|
+
/**
|
|
185
|
+
* The high and low watermarks for lines coverage. `[low, high]`
|
|
186
|
+
*/
|
|
187
|
+
lines?: number[];
|
|
188
|
+
/**
|
|
189
|
+
* The high and low watermarks for statements coverage. `[low, high]`
|
|
190
|
+
*/
|
|
191
|
+
statements?: number[];
|
|
192
|
+
};
|
|
113
193
|
export type SchemaReporter = ReporterReporter[] | string;
|
|
114
194
|
export type ReporterReporter = {
|
|
115
195
|
[key: string]: any;
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
|
|
3
3
|
// CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.Runner = exports.
|
|
6
|
-
var
|
|
7
|
-
(function (
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
})(
|
|
5
|
+
exports.Runner = exports.CoverageReporterEnum = void 0;
|
|
6
|
+
var CoverageReporterEnum;
|
|
7
|
+
(function (CoverageReporterEnum) {
|
|
8
|
+
CoverageReporterEnum["Cobertura"] = "cobertura";
|
|
9
|
+
CoverageReporterEnum["Html"] = "html";
|
|
10
|
+
CoverageReporterEnum["Json"] = "json";
|
|
11
|
+
CoverageReporterEnum["JsonSummary"] = "json-summary";
|
|
12
|
+
CoverageReporterEnum["Lcov"] = "lcov";
|
|
13
|
+
CoverageReporterEnum["Lcovonly"] = "lcovonly";
|
|
14
|
+
CoverageReporterEnum["Text"] = "text";
|
|
15
|
+
CoverageReporterEnum["TextSummary"] = "text-summary";
|
|
16
|
+
})(CoverageReporterEnum || (exports.CoverageReporterEnum = CoverageReporterEnum = {}));
|
|
17
17
|
/**
|
|
18
18
|
* Specifies the test runner to use for test execution.
|
|
19
19
|
*/
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"properties": {
|
|
7
7
|
"buildTarget": {
|
|
8
8
|
"type": "string",
|
|
9
|
-
"description": "Specifies the build target to use for the unit test build in the format `project:target[:configuration]`. You can also pass a comma-separated list of configurations. Example: `project:target:production,staging`.",
|
|
9
|
+
"description": "Specifies the build target to use for the unit test build in the format `project:target[:configuration]`. This defaults to the `build` target of the current project with the `development` configuration. You can also pass a comma-separated list of configurations. Example: `project:target:production,staging`.",
|
|
10
10
|
"pattern": "^[^:\\s]*:[^:\\s]*(:[^\\s]+)?$"
|
|
11
11
|
},
|
|
12
12
|
"tsConfig": {
|
|
13
13
|
"type": "string",
|
|
14
|
-
"description": "The path to the TypeScript configuration file, relative to the workspace root."
|
|
14
|
+
"description": "The path to the TypeScript configuration file, relative to the workspace root. Defaults to `tsconfig.spec.json` in the project root if it exists. If not specified and the default does not exist, the `tsConfig` from the specified `buildTarget` will be used."
|
|
15
15
|
},
|
|
16
16
|
"runner": {
|
|
17
17
|
"type": "string",
|
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
},
|
|
27
27
|
"minItems": 1
|
|
28
28
|
},
|
|
29
|
+
"browserViewport": {
|
|
30
|
+
"description": "Specifies the browser viewport dimensions for browser-based tests in the format `widthxheight`.",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"pattern": "^\\d+x\\d+$"
|
|
33
|
+
},
|
|
29
34
|
"include": {
|
|
30
35
|
"type": "array",
|
|
31
36
|
"items": {
|
|
@@ -54,25 +59,46 @@
|
|
|
54
59
|
"description": "Enables debugging mode for tests, allowing the use of the Node Inspector.",
|
|
55
60
|
"default": false
|
|
56
61
|
},
|
|
57
|
-
"
|
|
62
|
+
"coverage": {
|
|
58
63
|
"type": "boolean",
|
|
59
|
-
"description": "Enables
|
|
64
|
+
"description": "Enables coverage reporting for tests.",
|
|
60
65
|
"default": false
|
|
61
66
|
},
|
|
62
|
-
"
|
|
67
|
+
"coverageAll": {
|
|
68
|
+
"type": "boolean",
|
|
69
|
+
"description": "Includes all files that match the `coverageInclude` pattern in the coverage report, not just those touched by tests.",
|
|
70
|
+
"default": true
|
|
71
|
+
},
|
|
72
|
+
"coverageInclude": {
|
|
73
|
+
"type": "array",
|
|
74
|
+
"description": "Specifies glob patterns of files to include in the coverage report.",
|
|
75
|
+
"items": {
|
|
76
|
+
"type": "string"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"coverageExclude": {
|
|
63
80
|
"type": "array",
|
|
64
|
-
"description": "Specifies glob patterns of files to exclude from the
|
|
81
|
+
"description": "Specifies glob patterns of files to exclude from the coverage report.",
|
|
65
82
|
"items": {
|
|
66
83
|
"type": "string"
|
|
67
84
|
}
|
|
68
85
|
},
|
|
69
|
-
"
|
|
86
|
+
"coverageReporters": {
|
|
70
87
|
"type": "array",
|
|
71
|
-
"description": "Specifies the reporters to use for
|
|
88
|
+
"description": "Specifies the reporters to use for coverage results. Each reporter can be a string representing its name, or a tuple containing the name and an options object. Built-in reporters include 'html', 'lcov', 'lcovonly', 'text', 'text-summary', 'cobertura', 'json', and 'json-summary'.",
|
|
72
89
|
"items": {
|
|
73
90
|
"oneOf": [
|
|
74
91
|
{
|
|
75
|
-
"
|
|
92
|
+
"enum": [
|
|
93
|
+
"html",
|
|
94
|
+
"lcov",
|
|
95
|
+
"lcovonly",
|
|
96
|
+
"text",
|
|
97
|
+
"text-summary",
|
|
98
|
+
"cobertura",
|
|
99
|
+
"json",
|
|
100
|
+
"json-summary"
|
|
101
|
+
]
|
|
76
102
|
},
|
|
77
103
|
{
|
|
78
104
|
"type": "array",
|
|
@@ -80,7 +106,16 @@
|
|
|
80
106
|
"maxItems": 2,
|
|
81
107
|
"items": [
|
|
82
108
|
{
|
|
83
|
-
"
|
|
109
|
+
"enum": [
|
|
110
|
+
"html",
|
|
111
|
+
"lcov",
|
|
112
|
+
"lcovonly",
|
|
113
|
+
"text",
|
|
114
|
+
"text-summary",
|
|
115
|
+
"cobertura",
|
|
116
|
+
"json",
|
|
117
|
+
"json-summary"
|
|
118
|
+
]
|
|
84
119
|
},
|
|
85
120
|
{
|
|
86
121
|
"type": "object"
|
|
@@ -90,6 +125,68 @@
|
|
|
90
125
|
]
|
|
91
126
|
}
|
|
92
127
|
},
|
|
128
|
+
"coverageThresholds": {
|
|
129
|
+
"type": "object",
|
|
130
|
+
"description": "Specifies minimum coverage thresholds that must be met. If thresholds are not met, the builder will exit with an error.",
|
|
131
|
+
"properties": {
|
|
132
|
+
"perFile": {
|
|
133
|
+
"type": "boolean",
|
|
134
|
+
"description": "When true, thresholds are enforced for each file individually."
|
|
135
|
+
},
|
|
136
|
+
"statements": {
|
|
137
|
+
"type": "number",
|
|
138
|
+
"description": "Minimum percentage of statements covered."
|
|
139
|
+
},
|
|
140
|
+
"branches": {
|
|
141
|
+
"type": "number",
|
|
142
|
+
"description": "Minimum percentage of branches covered."
|
|
143
|
+
},
|
|
144
|
+
"functions": {
|
|
145
|
+
"type": "number",
|
|
146
|
+
"description": "Minimum percentage of functions covered."
|
|
147
|
+
},
|
|
148
|
+
"lines": {
|
|
149
|
+
"type": "number",
|
|
150
|
+
"description": "Minimum percentage of lines covered."
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
"additionalProperties": false
|
|
154
|
+
},
|
|
155
|
+
"coverageWatermarks": {
|
|
156
|
+
"type": "object",
|
|
157
|
+
"description": "Specifies coverage watermarks for the HTML reporter. These determine the color coding for high, medium, and low coverage.",
|
|
158
|
+
"properties": {
|
|
159
|
+
"statements": {
|
|
160
|
+
"type": "array",
|
|
161
|
+
"description": "The high and low watermarks for statements coverage. `[low, high]`",
|
|
162
|
+
"items": { "type": "number" },
|
|
163
|
+
"minItems": 2,
|
|
164
|
+
"maxItems": 2
|
|
165
|
+
},
|
|
166
|
+
"branches": {
|
|
167
|
+
"type": "array",
|
|
168
|
+
"description": "The high and low watermarks for branches coverage. `[low, high]`",
|
|
169
|
+
"items": { "type": "number" },
|
|
170
|
+
"minItems": 2,
|
|
171
|
+
"maxItems": 2
|
|
172
|
+
},
|
|
173
|
+
"functions": {
|
|
174
|
+
"type": "array",
|
|
175
|
+
"description": "The high and low watermarks for functions coverage. `[low, high]`",
|
|
176
|
+
"items": { "type": "number" },
|
|
177
|
+
"minItems": 2,
|
|
178
|
+
"maxItems": 2
|
|
179
|
+
},
|
|
180
|
+
"lines": {
|
|
181
|
+
"type": "array",
|
|
182
|
+
"description": "The high and low watermarks for lines coverage. `[low, high]`",
|
|
183
|
+
"items": { "type": "number" },
|
|
184
|
+
"minItems": 2,
|
|
185
|
+
"maxItems": 2
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
"additionalProperties": false
|
|
189
|
+
},
|
|
93
190
|
"reporters": {
|
|
94
191
|
"type": "array",
|
|
95
192
|
"description": "Specifies the reporters to use during test execution. Each reporter can be a string representing its name, or a tuple containing the name and an options object. Built-in reporters include 'default', 'verbose', 'dots', 'json', 'junit', 'tap', 'tap-flat', and 'html'. You can also provide a path to a custom reporter.",
|
|
@@ -98,10 +195,10 @@
|
|
|
98
195
|
{
|
|
99
196
|
"anyOf": [
|
|
100
197
|
{
|
|
101
|
-
"
|
|
198
|
+
"type": "string"
|
|
102
199
|
},
|
|
103
200
|
{
|
|
104
|
-
"
|
|
201
|
+
"enum": ["default", "verbose", "dots", "json", "junit", "tap", "tap-flat", "html"]
|
|
105
202
|
}
|
|
106
203
|
]
|
|
107
204
|
},
|
|
@@ -113,10 +210,19 @@
|
|
|
113
210
|
{
|
|
114
211
|
"anyOf": [
|
|
115
212
|
{
|
|
116
|
-
"
|
|
213
|
+
"type": "string"
|
|
117
214
|
},
|
|
118
215
|
{
|
|
119
|
-
"
|
|
216
|
+
"enum": [
|
|
217
|
+
"default",
|
|
218
|
+
"verbose",
|
|
219
|
+
"dots",
|
|
220
|
+
"json",
|
|
221
|
+
"junit",
|
|
222
|
+
"tap",
|
|
223
|
+
"tap-flat",
|
|
224
|
+
"html"
|
|
225
|
+
]
|
|
120
226
|
}
|
|
121
227
|
]
|
|
122
228
|
},
|
|
@@ -148,6 +254,11 @@
|
|
|
148
254
|
"type": "boolean",
|
|
149
255
|
"description": "Shows build progress information in the console. Defaults to the `progress` setting of the specified `buildTarget`."
|
|
150
256
|
},
|
|
257
|
+
"listTests": {
|
|
258
|
+
"type": "boolean",
|
|
259
|
+
"description": "Lists all discovered test files and exits the process without building or executing the tests.",
|
|
260
|
+
"default": false
|
|
261
|
+
},
|
|
151
262
|
"dumpVirtualFiles": {
|
|
152
263
|
"type": "boolean",
|
|
153
264
|
"description": "Dumps build output files to the `.angular/cache` directory for debugging purposes.",
|
|
@@ -156,23 +267,5 @@
|
|
|
156
267
|
}
|
|
157
268
|
},
|
|
158
269
|
"additionalProperties": false,
|
|
159
|
-
"required": ["
|
|
160
|
-
"definitions": {
|
|
161
|
-
"coverage-reporters": {
|
|
162
|
-
"enum": [
|
|
163
|
-
"html",
|
|
164
|
-
"lcov",
|
|
165
|
-
"lcovonly",
|
|
166
|
-
"text",
|
|
167
|
-
"text-summary",
|
|
168
|
-
"cobertura",
|
|
169
|
-
"json",
|
|
170
|
-
"json-summary"
|
|
171
|
-
]
|
|
172
|
-
},
|
|
173
|
-
"reporters-enum": {
|
|
174
|
-
"type": "string",
|
|
175
|
-
"enum": ["default", "verbose", "dots", "json", "junit", "tap", "tap-flat", "html"]
|
|
176
|
-
}
|
|
177
|
-
}
|
|
270
|
+
"required": ["runner"]
|
|
178
271
|
}
|
|
@@ -5,4 +5,28 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.dev/license
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Finds all test files in the project.
|
|
10
|
+
*
|
|
11
|
+
* @param include Glob patterns of files to include.
|
|
12
|
+
* @param exclude Glob patterns of files to exclude.
|
|
13
|
+
* @param workspaceRoot The absolute path to the workspace root.
|
|
14
|
+
* @param projectSourceRoot The absolute path to the project's source root.
|
|
15
|
+
* @returns A unique set of absolute paths to all test files.
|
|
16
|
+
*/
|
|
17
|
+
export declare function findTests(include: string[], exclude: string[], workspaceRoot: string, projectSourceRoot: string): Promise<string[]>;
|
|
18
|
+
interface TestEntrypointsOptions {
|
|
19
|
+
projectSourceRoot: string;
|
|
20
|
+
workspaceRoot: string;
|
|
21
|
+
removeTestExtension?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Generates unique, dash-delimited bundle names for a set of test files.
|
|
25
|
+
* This is used to create distinct output files for each test.
|
|
26
|
+
*
|
|
27
|
+
* @param testFiles An array of absolute paths to test files.
|
|
28
|
+
* @param options Configuration options for generating entry points.
|
|
29
|
+
* @returns A map where keys are the generated unique bundle names and values are the original file paths.
|
|
30
|
+
*/
|
|
31
|
+
export declare function getTestEntrypoints(testFiles: string[], { projectSourceRoot, workspaceRoot, removeTestExtension }: TestEntrypointsOptions): Map<string, string>;
|
|
32
|
+
export {};
|
|
@@ -7,8 +7,197 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.dev/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
exports.findTests = findTests;
|
|
11
|
+
exports.getTestEntrypoints = getTestEntrypoints;
|
|
12
|
+
const node_fs_1 = require("node:fs");
|
|
13
|
+
const node_path_1 = require("node:path");
|
|
14
|
+
const tinyglobby_1 = require("tinyglobby");
|
|
15
|
+
const path_1 = require("../../utils/path");
|
|
16
|
+
/**
|
|
17
|
+
* Finds all test files in the project.
|
|
18
|
+
*
|
|
19
|
+
* @param include Glob patterns of files to include.
|
|
20
|
+
* @param exclude Glob patterns of files to exclude.
|
|
21
|
+
* @param workspaceRoot The absolute path to the workspace root.
|
|
22
|
+
* @param projectSourceRoot The absolute path to the project's source root.
|
|
23
|
+
* @returns A unique set of absolute paths to all test files.
|
|
24
|
+
*/
|
|
25
|
+
async function findTests(include, exclude, workspaceRoot, projectSourceRoot) {
|
|
26
|
+
const staticMatches = new Set();
|
|
27
|
+
const dynamicPatterns = [];
|
|
28
|
+
const normalizedExcludes = exclude.map((p) => normalizePattern(p, workspaceRoot, projectSourceRoot));
|
|
29
|
+
// 1. Separate static and dynamic patterns
|
|
30
|
+
for (const pattern of include) {
|
|
31
|
+
const normalized = normalizePattern(pattern, workspaceRoot, projectSourceRoot);
|
|
32
|
+
if ((0, tinyglobby_1.isDynamicPattern)(normalized)) {
|
|
33
|
+
dynamicPatterns.push(normalized);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const result = await handleStaticPattern(normalized, projectSourceRoot);
|
|
37
|
+
if (Array.isArray(result)) {
|
|
38
|
+
result.forEach((file) => staticMatches.add(file));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// It was a static path that didn't resolve to a spec, treat as dynamic
|
|
42
|
+
dynamicPatterns.push(result);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// 2. Execute a single glob for all dynamic patterns
|
|
47
|
+
if (dynamicPatterns.length > 0) {
|
|
48
|
+
const globMatches = await (0, tinyglobby_1.glob)(dynamicPatterns, {
|
|
49
|
+
cwd: projectSourceRoot,
|
|
50
|
+
absolute: true,
|
|
51
|
+
ignore: ['**/node_modules/**', ...normalizedExcludes],
|
|
52
|
+
});
|
|
53
|
+
for (const match of globMatches) {
|
|
54
|
+
staticMatches.add(match);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// 3. Combine and de-duplicate results
|
|
58
|
+
return [...staticMatches];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generates unique, dash-delimited bundle names for a set of test files.
|
|
62
|
+
* This is used to create distinct output files for each test.
|
|
63
|
+
*
|
|
64
|
+
* @param testFiles An array of absolute paths to test files.
|
|
65
|
+
* @param options Configuration options for generating entry points.
|
|
66
|
+
* @returns A map where keys are the generated unique bundle names and values are the original file paths.
|
|
67
|
+
*/
|
|
68
|
+
function getTestEntrypoints(testFiles, { projectSourceRoot, workspaceRoot, removeTestExtension }) {
|
|
69
|
+
const seen = new Set();
|
|
70
|
+
const roots = [projectSourceRoot, workspaceRoot];
|
|
71
|
+
return new Map(Array.from(testFiles, (testFile) => {
|
|
72
|
+
const fileName = generateNameFromPath(testFile, roots, !!removeTestExtension);
|
|
73
|
+
const baseName = `spec-${fileName}`;
|
|
74
|
+
let uniqueName = baseName;
|
|
75
|
+
let suffix = 2;
|
|
76
|
+
while (seen.has(uniqueName)) {
|
|
77
|
+
uniqueName = `${baseName}-${suffix}`.replace(/([^\w](?:spec|test))-([\d]+)$/, '-$2$1');
|
|
78
|
+
++suffix;
|
|
79
|
+
}
|
|
80
|
+
seen.add(uniqueName);
|
|
81
|
+
return [uniqueName, testFile];
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Generates a unique, dash-delimited name from a file path.
|
|
86
|
+
* This is used to create a consistent and readable bundle name for a given test file.
|
|
87
|
+
* @param testFile The absolute path to the test file.
|
|
88
|
+
* @param roots An array of root paths to remove from the beginning of the test file path.
|
|
89
|
+
* @param removeTestExtension Whether to remove the `.spec` or `.test` extension from the result.
|
|
90
|
+
* @returns A dash-cased name derived from the relative path of the test file.
|
|
91
|
+
*/
|
|
92
|
+
function generateNameFromPath(testFile, roots, removeTestExtension) {
|
|
93
|
+
const relativePath = removeRoots(testFile, roots);
|
|
94
|
+
let startIndex = 0;
|
|
95
|
+
// Skip leading dots and slashes
|
|
96
|
+
while (startIndex < relativePath.length && /^[./\\]$/.test(relativePath[startIndex])) {
|
|
97
|
+
startIndex++;
|
|
98
|
+
}
|
|
99
|
+
let endIndex = relativePath.length;
|
|
100
|
+
if (removeTestExtension) {
|
|
101
|
+
const match = relativePath.match(/\.(spec|test)\.[^.]+$/);
|
|
102
|
+
if (match?.index) {
|
|
103
|
+
endIndex = match.index;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
const extIndex = relativePath.lastIndexOf('.');
|
|
108
|
+
if (extIndex > startIndex) {
|
|
109
|
+
endIndex = extIndex;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Build the final string in a single pass
|
|
113
|
+
let result = '';
|
|
114
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
115
|
+
const char = relativePath[i];
|
|
116
|
+
result += char === '/' || char === '\\' ? '-' : char;
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
const removeLeadingSlash = (pattern) => {
|
|
121
|
+
if (pattern.charAt(0) === '/') {
|
|
122
|
+
return pattern.substring(1);
|
|
123
|
+
}
|
|
124
|
+
return pattern;
|
|
125
|
+
};
|
|
126
|
+
const removeRelativeRoot = (path, root) => {
|
|
127
|
+
if (path.startsWith(root)) {
|
|
128
|
+
return path.substring(root.length);
|
|
129
|
+
}
|
|
130
|
+
return path;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Removes potential root paths from a file path, returning a relative path.
|
|
134
|
+
* If no root path matches, it returns the file's basename.
|
|
135
|
+
*/
|
|
136
|
+
function removeRoots(path, roots) {
|
|
137
|
+
for (const root of roots) {
|
|
138
|
+
if (path.startsWith(root)) {
|
|
139
|
+
return path.substring(root.length);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return (0, node_path_1.basename)(path);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Normalizes a glob pattern by converting it to a POSIX path, removing leading slashes,
|
|
146
|
+
* and making it relative to the project source root.
|
|
147
|
+
*
|
|
148
|
+
* @param pattern The glob pattern to normalize.
|
|
149
|
+
* @param workspaceRoot The absolute path to the workspace root.
|
|
150
|
+
* @param projectSourceRoot The absolute path to the project's source root.
|
|
151
|
+
* @returns A normalized glob pattern.
|
|
152
|
+
*/
|
|
153
|
+
function normalizePattern(pattern, workspaceRoot, projectSourceRoot) {
|
|
154
|
+
// normalize pattern, glob lib only accepts forward slashes
|
|
155
|
+
let normalizedPattern = (0, path_1.toPosixPath)(pattern);
|
|
156
|
+
normalizedPattern = removeLeadingSlash(normalizedPattern);
|
|
157
|
+
const relativeProjectRoot = (0, path_1.toPosixPath)((0, node_path_1.relative)(workspaceRoot, projectSourceRoot) + '/');
|
|
158
|
+
// remove relativeProjectRoot to support relative paths from root
|
|
159
|
+
// such paths are easy to get when running scripts via IDEs
|
|
160
|
+
return removeRelativeRoot(normalizedPattern, relativeProjectRoot);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Handles static (non-glob) patterns by attempting to resolve them to a directory
|
|
164
|
+
* of spec files or a corresponding `.spec` file.
|
|
165
|
+
*
|
|
166
|
+
* @param pattern The static path pattern.
|
|
167
|
+
* @param projectSourceRoot The absolute path to the project's source root.
|
|
168
|
+
* @returns A promise that resolves to either an array of found spec files, a new glob pattern,
|
|
169
|
+
* or the original pattern if no special handling was applied.
|
|
170
|
+
*/
|
|
171
|
+
async function handleStaticPattern(pattern, projectSourceRoot) {
|
|
172
|
+
const fullPath = (0, node_path_1.join)(projectSourceRoot, pattern);
|
|
173
|
+
if (await isDirectory(fullPath)) {
|
|
174
|
+
return `${pattern}/**/*.spec.@(ts|tsx)`;
|
|
175
|
+
}
|
|
176
|
+
const fileExt = (0, node_path_1.extname)(pattern);
|
|
177
|
+
// Replace extension to `.spec.ext`. Example: `src/app/app.component.ts`-> `src/app/app.component.spec.ts`
|
|
178
|
+
const potentialSpec = (0, node_path_1.join)(projectSourceRoot, (0, node_path_1.dirname)(pattern), `${(0, node_path_1.basename)(pattern, fileExt)}.spec${fileExt}`);
|
|
179
|
+
if (await exists(potentialSpec)) {
|
|
180
|
+
return [potentialSpec];
|
|
181
|
+
}
|
|
182
|
+
return pattern;
|
|
183
|
+
}
|
|
184
|
+
/** Checks if a path exists and is a directory. */
|
|
185
|
+
async function isDirectory(path) {
|
|
186
|
+
try {
|
|
187
|
+
const stats = await node_fs_1.promises.stat(path);
|
|
188
|
+
return stats.isDirectory();
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/** Checks if a path exists on the file system. */
|
|
195
|
+
async function exists(path) {
|
|
196
|
+
try {
|
|
197
|
+
await node_fs_1.promises.access(path, node_fs_1.constants.F_OK);
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -30,7 +30,7 @@ function replaceBootstrap(getTypeChecker) {
|
|
|
30
30
|
if (target.text === PLATFORM_BROWSER_DYNAMIC_NAME) {
|
|
31
31
|
if (!bootstrapNamespace) {
|
|
32
32
|
bootstrapNamespace = nodeFactory.createUniqueName('__NgCli_bootstrap_');
|
|
33
|
-
bootstrapImport = nodeFactory.createImportDeclaration(undefined, nodeFactory.createImportClause(
|
|
33
|
+
bootstrapImport = nodeFactory.createImportDeclaration(undefined, nodeFactory.createImportClause(undefined, undefined, nodeFactory.createNamespaceImport(bootstrapNamespace)), nodeFactory.createStringLiteral('@angular/platform-browser'));
|
|
34
34
|
}
|
|
35
35
|
replacedNodes.push(target);
|
|
36
36
|
return nodeFactory.updateCallExpression(node, nodeFactory.createPropertyAccessExpression(bootstrapNamespace, 'platformBrowser'), node.typeArguments, node.arguments);
|