Skip to content

Commit a7e81d2

Browse files
committed
feat(@schematics/angular): add migration to add istanbul-lib-instrument
Add a new schematic migration to automatically add istanbul-lib-instrument to devDependencies for projects that use Karma. Covered builders: - @angular-devkit/build-angular:karma - @angular/build:karma - @angular/build:unit-test (when runner is 'karma')
1 parent 852b759 commit a7e81d2

File tree

4 files changed

+233
-0
lines changed

4 files changed

+233
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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+
9+
import { Rule } from '@angular-devkit/schematics';
10+
import { DependencyType, ExistingBehavior, addDependency } from '../../utility/dependency';
11+
import { latestVersions } from '../../utility/latest-versions';
12+
import { allTargetOptions, getWorkspace } from '../../utility/workspace';
13+
import { Builders } from '../../utility/workspace-models';
14+
15+
export default function (): Rule {
16+
return async (tree) => {
17+
const workspace = await getWorkspace(tree);
18+
let needInstrumenter = false;
19+
20+
for (const [, project] of workspace.projects) {
21+
for (const [, target] of project.targets) {
22+
if (target.builder === Builders.Karma || target.builder === Builders.BuildKarma) {
23+
needInstrumenter = true;
24+
break;
25+
}
26+
27+
if (target.builder === Builders.BuildUnitTest) {
28+
for (const [, options] of allTargetOptions(target)) {
29+
if (options['runner'] === 'karma') {
30+
needInstrumenter = true;
31+
break;
32+
}
33+
}
34+
}
35+
36+
if (needInstrumenter) {
37+
break;
38+
}
39+
}
40+
if (needInstrumenter) {
41+
break;
42+
}
43+
}
44+
45+
if (needInstrumenter) {
46+
return addDependency('istanbul-lib-instrument', latestVersions['istanbul-lib-instrument'], {
47+
type: DependencyType.Dev,
48+
existing: ExistingBehavior.Skip,
49+
});
50+
}
51+
};
52+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
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+
9+
/* eslint-disable @typescript-eslint/no-explicit-any */
10+
11+
import { EmptyTree } from '@angular-devkit/schematics';
12+
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
13+
14+
describe('Migration to add istanbul-lib-instrument', () => {
15+
const schematicRunner = new SchematicTestRunner(
16+
'migrations',
17+
require.resolve('../migration-collection.json'),
18+
);
19+
20+
let tree: UnitTestTree;
21+
beforeEach(() => {
22+
tree = new UnitTestTree(new EmptyTree());
23+
tree.create(
24+
'/package.json',
25+
JSON.stringify({
26+
devDependencies: {},
27+
}),
28+
);
29+
});
30+
31+
function createWorkspace(workspace: any) {
32+
tree.create('/angular.json', JSON.stringify(workspace));
33+
}
34+
35+
async function expectDependency(defined: boolean) {
36+
const newTree = await schematicRunner.runSchematic('add-istanbul-instrumenter', {}, tree);
37+
const { devDependencies } = newTree.readJson('/package.json') as any;
38+
if (defined) {
39+
expect(devDependencies['istanbul-lib-instrument']).toBeDefined();
40+
} else {
41+
expect(devDependencies['istanbul-lib-instrument']).toBeUndefined();
42+
}
43+
}
44+
45+
it('should add istanbul-lib-instrument for @angular-devkit/build-angular:karma', async () => {
46+
createWorkspace({
47+
version: 1,
48+
projects: {
49+
app: {
50+
targets: {
51+
test: {
52+
builder: '@angular-devkit/build-angular:karma',
53+
},
54+
},
55+
},
56+
},
57+
});
58+
59+
await expectDependency(true);
60+
});
61+
62+
it('should add istanbul-lib-instrument for @angular/build:karma', async () => {
63+
createWorkspace({
64+
version: 1,
65+
projects: {
66+
app: {
67+
targets: {
68+
test: {
69+
builder: '@angular/build:karma',
70+
},
71+
},
72+
},
73+
},
74+
});
75+
76+
await expectDependency(true);
77+
});
78+
79+
it('should add istanbul-lib-instrument for @angular/build:unit-test with runner: karma', async () => {
80+
createWorkspace({
81+
version: 1,
82+
projects: {
83+
app: {
84+
targets: {
85+
test: {
86+
builder: '@angular/build:unit-test',
87+
options: {
88+
runner: 'karma',
89+
},
90+
},
91+
},
92+
},
93+
},
94+
});
95+
96+
await expectDependency(true);
97+
});
98+
99+
it('should add istanbul-lib-instrument if runner: karma is in configuration', async () => {
100+
createWorkspace({
101+
version: 1,
102+
projects: {
103+
app: {
104+
targets: {
105+
test: {
106+
builder: '@angular/build:unit-test',
107+
configurations: {
108+
ci: {
109+
runner: 'karma',
110+
},
111+
},
112+
},
113+
},
114+
},
115+
},
116+
});
117+
118+
await expectDependency(true);
119+
});
120+
121+
it('should NOT add istanbul-lib-instrument for @angular/build:unit-test with runner: vitest', async () => {
122+
createWorkspace({
123+
version: 1,
124+
projects: {
125+
app: {
126+
targets: {
127+
test: {
128+
builder: '@angular/build:unit-test',
129+
options: {
130+
runner: 'vitest',
131+
},
132+
},
133+
},
134+
},
135+
},
136+
});
137+
138+
await expectDependency(false);
139+
});
140+
141+
it('should NOT add istanbul-lib-instrument for @angular/build:unit-test with no runner specified (default vitest)', async () => {
142+
createWorkspace({
143+
version: 1,
144+
projects: {
145+
app: {
146+
targets: {
147+
test: {
148+
builder: '@angular/build:unit-test',
149+
options: {},
150+
},
151+
},
152+
},
153+
},
154+
});
155+
156+
await expectDependency(false);
157+
});
158+
159+
it('should NOT add istanbul-lib-instrument if no karma builder is used', async () => {
160+
createWorkspace({
161+
version: 1,
162+
projects: {
163+
app: {
164+
targets: {
165+
test: {
166+
builder: '@angular-devkit/build-angular:browser',
167+
},
168+
},
169+
},
170+
},
171+
});
172+
173+
await expectDependency(false);
174+
});
175+
});

packages/schematics/angular/migrations/migration-collection.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
{
22
"encapsulation": false,
33
"schematics": {
4+
"add-istanbul-instrumenter": {
5+
"version": "22.0.0",
6+
"factory": "./add-istanbul-instrumenter/migration",
7+
"description": "Add istanbul-lib-instrument to devDependencies if Karma unit testing is used."
8+
},
49
"use-application-builder": {
510
"version": "22.0.0",
611
"factory": "./use-application-builder/migration",

packages/schematics/angular/utility/latest-versions/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"@types/node": "^20.17.19",
99
"browser-sync": "^3.0.0",
1010
"express": "^5.1.0",
11+
"istanbul-lib-instrument": "^6.0.3",
1112
"jasmine-core": "~6.1.0",
1213
"jasmine-spec-reporter": "~7.0.0",
1314
"karma-chrome-launcher": "~3.2.0",

0 commit comments

Comments
 (0)