/
update-karma-main-file.ts
119 lines (104 loc) · 3.46 KB
/
update-karma-main-file.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { chain, Rule, Tree } from '@angular-devkit/schematics';
import * as ts from 'typescript';
import { readWorkspace } from '@schematics/angular/utility';
import { Builders } from '@schematics/angular/utility/workspace-models';
import { allTargetOptions } from '@schematics/angular/utility/workspace';
import { formatFiles } from '@nrwl/workspace';
export default function (): Rule {
return chain([
async (host) => {
for (const file of await findTestMainFiles(host)) {
updateTestFile(host, file);
}
},
formatFiles(),
]);
}
async function findTestMainFiles(host: Tree): Promise<Set<string>> {
const testFiles = new Set<string>();
const workspace = await readWorkspace(host);
// find all test.ts files.
for (const project of workspace.projects.values()) {
for (const target of project.targets.values()) {
if (target.builder !== Builders.Karma) {
continue;
}
for (const [, options] of allTargetOptions(target)) {
if (typeof options.main === 'string' && host.exists(options.main)) {
testFiles.add(options.main);
}
}
}
}
return testFiles;
}
function updateTestFile(host: Tree, file: string): void {
const content = host.readText(file);
if (!content.includes('require.context')) {
return;
}
const sourceFile = ts.createSourceFile(
file,
content.replace(/^\uFEFF/, ''),
ts.ScriptTarget.Latest,
true
);
const usedVariableNames = new Set<string>();
const recorder = host.beginUpdate(sourceFile.fileName);
ts.forEachChild(sourceFile, (node) => {
if (ts.isVariableStatement(node)) {
const variableDeclaration = node.declarationList.declarations[0];
if (
ts
.getModifiers(node)
?.some((m) => m.kind === ts.SyntaxKind.DeclareKeyword)
) {
// `declare const require`
if (variableDeclaration.name.getText() !== 'require') {
return;
}
} else {
// `const context = require.context('./', true, /\.spec\.ts$/);`
if (
!variableDeclaration.initializer
?.getText()
.startsWith('require.context')
) {
return;
}
// add variable name as used.
usedVariableNames.add(variableDeclaration.name.getText());
}
// Delete node.
recorder.remove(node.getFullStart(), node.getFullWidth());
}
if (
usedVariableNames.size &&
ts.isExpressionStatement(node) && // context.keys().map(context);
ts.isCallExpression(node.expression) && // context.keys().map(context);
ts.isPropertyAccessExpression(node.expression.expression) && // context.keys().map
ts.isCallExpression(node.expression.expression.expression) && // context.keys()
ts.isPropertyAccessExpression(
node.expression.expression.expression.expression
) && // context.keys
ts.isIdentifier(
node.expression.expression.expression.expression.expression
) && // context
usedVariableNames.has(
node.expression.expression.expression.expression.expression.getText()
)
) {
// `context.keys().map(context);`
// `context.keys().forEach(context);`
recorder.remove(node.getFullStart(), node.getFullWidth());
}
});
host.commitUpdate(recorder);
}