Skip to content

Commit f46e2af

Browse files
author
Angular Builds
committed
7068de280 refactor(@angular-devkit/build-angular): clean find tests logic
1 parent 4041f1c commit f46e2af

File tree

7 files changed

+61
-90
lines changed

7 files changed

+61
-90
lines changed

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"name": "@angular-devkit/build-angular",
3-
"version": "13.3.0-next.0",
3+
"version": "14.0.0-next.0",
44
"description": "Angular Webpack Build Facade",
55
"main": "src/index.js",
66
"typings": "src/index.d.ts",
77
"builders": "builders.json",
88
"dependencies": {
99
"@ampproject/remapping": "1.1.1",
10-
"@angular-devkit/architect": "github:angular/angular-devkit-architect-builds#8278b56c9",
11-
"@angular-devkit/build-webpack": "github:angular/angular-devkit-build-webpack-builds#8278b56c9",
12-
"@angular-devkit/core": "github:angular/angular-devkit-core-builds#8278b56c9",
10+
"@angular-devkit/architect": "github:angular/angular-devkit-architect-builds#7068de280",
11+
"@angular-devkit/build-webpack": "github:angular/angular-devkit-build-webpack-builds#7068de280",
12+
"@angular-devkit/core": "github:angular/angular-devkit-core-builds#7068de280",
1313
"@babel/core": "7.16.12",
1414
"@babel/generator": "7.16.8",
1515
"@babel/helper-annotate-as-pure": "7.16.7",
@@ -20,7 +20,7 @@
2020
"@babel/runtime": "7.16.7",
2121
"@babel/template": "7.16.7",
2222
"@discoveryjs/json-ext": "0.5.6",
23-
"@ngtools/webpack": "github:angular/ngtools-webpack-builds#8278b56c9",
23+
"@ngtools/webpack": "github:angular/ngtools-webpack-builds#7068de280",
2424
"ansi-colors": "4.1.1",
2525
"babel-loader": "8.2.3",
2626
"babel-plugin-istanbul": "6.1.1",

src/builders/karma/find-tests.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
export declare function findTests(patterns: string[], cwd: string, workspaceRoot: string): string[];
8+
export declare function findTests(patterns: string[], workspaceRoot: string, projectSourceRoot: string): Promise<string[]>;

src/builders/karma/find-tests.js

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,48 +28,62 @@ var __importStar = (this && this.__importStar) || function (mod) {
2828
Object.defineProperty(exports, "__esModule", { value: true });
2929
exports.findTests = void 0;
3030
const fs_1 = require("fs");
31-
const glob = __importStar(require("glob"));
31+
const glob_1 = __importStar(require("glob"));
3232
const path_1 = require("path");
33-
const is_directory_1 = require("../../utils/is-directory");
33+
const util_1 = require("util");
34+
const globPromise = (0, util_1.promisify)(glob_1.default);
3435
// go through all patterns and find unique list of files
35-
function findTests(patterns, cwd, workspaceRoot) {
36-
return patterns.reduce((files, pattern) => {
37-
const relativePathToMain = cwd.replace(workspaceRoot, '').substr(1); // remove leading slash
38-
const tests = findMatchingTests(pattern, cwd, relativePathToMain);
39-
tests.forEach((file) => {
40-
if (!files.includes(file)) {
41-
files.push(file);
42-
}
43-
});
44-
return files;
45-
}, []);
36+
async function findTests(patterns, workspaceRoot, projectSourceRoot) {
37+
const matchingTestsPromises = patterns.map((pattern) => findMatchingTests(pattern, workspaceRoot, projectSourceRoot));
38+
const files = await Promise.all(matchingTestsPromises);
39+
// Unique file names
40+
return [...new Set(files.flat())];
4641
}
4742
exports.findTests = findTests;
48-
function findMatchingTests(pattern, cwd, relativePathToMain) {
43+
const normalizePath = (path) => path.replace(/\\/g, '/');
44+
async function findMatchingTests(pattern, workspaceRoot, projectSourceRoot) {
4945
// normalize pattern, glob lib only accepts forward slashes
50-
pattern = pattern.replace(/\\/g, '/');
51-
relativePathToMain = relativePathToMain.replace(/\\/g, '/');
52-
// remove relativePathToMain to support relative paths from root
46+
let normalizedPattern = normalizePath(pattern);
47+
const relativeProjectRoot = normalizePath((0, path_1.relative)(workspaceRoot, projectSourceRoot) + '/');
48+
// remove relativeProjectRoot to support relative paths from root
5349
// such paths are easy to get when running scripts via IDEs
54-
if (pattern.startsWith(relativePathToMain + '/')) {
55-
pattern = pattern.substr(relativePathToMain.length + 1); // +1 to include slash
50+
if (normalizedPattern.startsWith(relativeProjectRoot)) {
51+
normalizedPattern = normalizedPattern.substring(relativeProjectRoot.length);
5652
}
5753
// special logic when pattern does not look like a glob
58-
if (!glob.hasMagic(pattern)) {
59-
if ((0, is_directory_1.isDirectory)((0, path_1.join)(cwd, pattern))) {
60-
pattern = `${pattern}/**/*.spec.@(ts|tsx)`;
54+
if (!(0, glob_1.hasMagic)(normalizedPattern)) {
55+
if (await isDirectory((0, path_1.join)(projectSourceRoot, normalizedPattern))) {
56+
normalizedPattern = `${normalizedPattern}/**/*.spec.@(ts|tsx)`;
6157
}
6258
else {
6359
// see if matching spec file exists
64-
const extension = (0, path_1.extname)(pattern);
65-
const matchingSpec = `${(0, path_1.basename)(pattern, extension)}.spec${extension}`;
66-
if ((0, fs_1.existsSync)((0, path_1.join)(cwd, (0, path_1.dirname)(pattern), matchingSpec))) {
67-
pattern = (0, path_1.join)((0, path_1.dirname)(pattern), matchingSpec).replace(/\\/g, '/');
60+
const fileExt = (0, path_1.extname)(normalizedPattern);
61+
// Replace extension to `.spec.ext`. Example: `src/app/app.component.ts`-> `src/app/app.component.spec.ts`
62+
const potentialSpec = (0, path_1.join)((0, path_1.dirname)(normalizedPattern), `${(0, path_1.basename)(normalizedPattern, fileExt)}.spec${fileExt}`);
63+
if (await exists((0, path_1.join)(projectSourceRoot, potentialSpec))) {
64+
return [normalizePath(potentialSpec)];
6865
}
6966
}
7067
}
71-
const files = glob.sync(pattern, {
72-
cwd,
68+
return globPromise(normalizedPattern, {
69+
cwd: projectSourceRoot,
7370
});
74-
return files;
71+
}
72+
async function isDirectory(path) {
73+
try {
74+
const stats = await fs_1.promises.stat(path);
75+
return stats.isDirectory();
76+
}
77+
catch {
78+
return false;
79+
}
80+
}
81+
async function exists(path) {
82+
try {
83+
await fs_1.promises.access(path, fs_1.constants.F_OK);
84+
return true;
85+
}
86+
catch {
87+
return false;
88+
}
7589
}

src/builders/karma/index.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function execute(options, context, transforms = {}) {
8080
singleRun = !options.watch;
8181
}
8282
return (0, rxjs_1.from)(initialize(options, context, transforms.webpackConfiguration)).pipe((0, operators_1.switchMap)(async ([karma, webpackConfig]) => {
83-
var _a;
83+
var _a, _b, _c, _d, _e;
8484
const karmaOptions = {
8585
singleRun,
8686
};
@@ -98,23 +98,28 @@ function execute(options, context, transforms = {}) {
9898
}
9999
}
100100
// prepend special webpack loader that will transform test.ts
101-
if (options.include && options.include.length > 0) {
102-
const mainFilePath = (0, core_1.getSystemPath)((0, core_1.join)((0, core_1.normalize)(context.workspaceRoot), options.main));
103-
const files = (0, find_tests_1.findTests)(options.include, (0, path_1.dirname)(mainFilePath), context.workspaceRoot);
101+
if ((_a = options.include) === null || _a === void 0 ? void 0 : _a.length) {
102+
const projectName = (_b = context.target) === null || _b === void 0 ? void 0 : _b.project;
103+
if (!projectName) {
104+
throw new Error('The builder requires a target.');
105+
}
106+
const projectMetadata = await context.getProjectMetadata(projectName);
107+
const projectSourceRoot = (0, core_1.getSystemPath)((0, core_1.join)((0, core_1.normalize)(context.workspaceRoot), (_c = projectMetadata.root) !== null && _c !== void 0 ? _c : '', (_d = projectMetadata.sourceRoot) !== null && _d !== void 0 ? _d : ''));
108+
const files = await (0, find_tests_1.findTests)(options.include, context.workspaceRoot, projectSourceRoot);
104109
// early exit, no reason to start karma
105110
if (!files.length) {
106111
throw new Error(`Specified patterns: "${options.include.join(', ')}" did not match any spec files.`);
107112
}
108113
// Get the rules and ensure the Webpack configuration is setup properly
109-
const rules = ((_a = webpackConfig.module) === null || _a === void 0 ? void 0 : _a.rules) || [];
114+
const rules = ((_e = webpackConfig.module) === null || _e === void 0 ? void 0 : _e.rules) || [];
110115
if (!webpackConfig.module) {
111116
webpackConfig.module = { rules };
112117
}
113118
else if (!webpackConfig.module.rules) {
114119
webpackConfig.module.rules = rules;
115120
}
116121
rules.unshift({
117-
test: mainFilePath,
122+
test: (0, path_1.resolve)(context.workspaceRoot, options.main),
118123
use: {
119124
// cannot be a simple path as it differs between environments
120125
loader: single_test_transform_1.SingleTestTransformLoader,

src/utils/is-directory.d.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/utils/is-directory.js

Lines changed: 0 additions & 40 deletions
This file was deleted.

uniqueId

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Wed Jan 26 2022 22:12:31 GMT+0000 (Coordinated Universal Time)
1+
Thu Jan 27 2022 19:37:29 GMT+0000 (Coordinated Universal Time)

0 commit comments

Comments
 (0)