Skip to content

Commit e40a0cd

Browse files
committed
fixup! refactor(@angular/cli): add a get Zoneless/OnPush MCP tool
1 parent f336ca0 commit e40a0cd

5 files changed

Lines changed: 20 additions & 24 deletions

File tree

packages/angular/cli/BUILD.bazel

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ ts_project(
7070
"//:node_modules/@types/semver",
7171
"//:node_modules/@types/yargs",
7272
"//:node_modules/@types/yarnpkg__lockfile",
73-
"//:node_modules/fast-glob",
7473
"//:node_modules/listr2",
7574
"//:node_modules/semver",
7675
"//:node_modules/typescript",

packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import { glob } from 'fast-glob';
10-
import * as fs from 'fs';
11-
import { dirname, join } from 'path';
9+
import { glob } from 'node:fs/promises';
10+
import * as fs from 'node:fs';
11+
import { dirname, join } from 'node:path';
1212
import ts from 'typescript';
1313
import { createFixResponseForZoneTests, createProvideZonelessForTestsSetupPrompt } from './prompts';
1414
import { MigrationResponse } from './types';
@@ -51,7 +51,7 @@ export async function searchForGlobalZoneless(startPath: string): Promise<boolea
5151

5252
try {
5353
const files = await glob(`${angularJsonDir}/**/*.ts`);
54-
for (const file of files) {
54+
for await (const file of files) {
5555
const content = fs.readFileSync(file, 'utf-8');
5656
if (
5757
content.includes('initTestEnvironment') &&

packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/prompts.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,6 @@ export function createProvideZonelessForTestsSetupPrompt(testFilePath: string):
5454
});
5555
// ... rest of the test
5656
});
57-
58-
// Example for a group of failing tests
59-
describe('tests that require Zone.js', () => {
60-
beforeEach(() => {
61-
TestBed.configureTestingModule({
62-
providers: [provideZoneChangeDetection()]
63-
});
64-
});
65-
66-
// ... all failing tests go here
67-
});
6857
\`\`\`
6958
7059
### IMPORTANT: Rules and Constraints
@@ -74,6 +63,7 @@ export function createProvideZonelessForTestsSetupPrompt(testFilePath: string):
7463
2. **DO** add \`provideZoneChangeDetection()\` to the providers for each individual test or group of tests that fail after the change in Step 1.
7564
3. **DO NOT** attempt to fix the logic of the failing tests at this stage. The goal is only to enable zoneless for the suite and isolate the incompatible tests.
7665
4. **DO NOT** make any other changes to the test file or any application code.
66+
5. **DO NOT** move tests around or create new describe blocks if it can be avoided. Changes are easier to review when code moves around less.
7767
7868
### Final Step
7969
After you have applied all the required changes and followed all the rules, consult this tool again for the next steps in the migration process.`;
@@ -221,8 +211,9 @@ When running tests in a zoneless environment, you may encounter new types of fai
221211
You must follow these rules without exception:
222212
1. **DO** focus only on fixing the tests for the code in \`${fileOrDirPath}\`.
223213
2. **DO** apply the solutions described in the debugging guide to fix test failures.
224-
3. **DO NOT** make changes to application code unless it is to fix a bug revealed by the zoneless migration (e.g., converting a property to a signal to fix an \`ExpressionChangedAfterItHasBeenCheckedError\`).
225-
4. **DO NOT** re-introduce \`provideZoneChangeDetection()\` into tests that are already using \`provideZonelessChangeDetection()\`.
214+
3. **DO** update properties of test components to use signals. Tests often use plain objects and values and update the component state directly before calling \`fixture.detectChanges\`. This will not work and will result in \`ExpressionChangedAfterItHasBeenCheckedError\` because Angular was not notifed of the change.
215+
4. **DO NOT** make changes to application code unless it is to fix a bug revealed by the zoneless migration (e.g., converting a property to a signal to fix an \`ExpressionChangedAfterItHasBeenCheckedError\`).
216+
5. **DO NOT** re-introduce \`provideZoneChangeDetection()\` into tests that are already using \`provideZonelessChangeDetection()\`.
226217
`;
227218

228219
return createResponse(text);

packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/ts_utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import * as fs from 'fs';
9+
import * as fs from 'node:fs';
1010
import ts from 'typescript';
1111

1212
/**

packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol';
1010
import { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types';
11-
import { glob } from 'fast-glob';
12-
import * as fs from 'fs';
11+
import { glob } from 'node:fs/promises';
12+
import * as fs from 'node:fs';
1313
import ts from 'typescript';
1414
import { z } from 'zod';
1515
import { declareTool } from '../tool-registry';
@@ -53,8 +53,10 @@ export async function registerZonelessMigrationTool(
5353
const zoneFiles = new Set<ts.SourceFile>();
5454

5555
if (fs.statSync(fileOrDirPath).isDirectory()) {
56-
const allFiles = await glob(`${fileOrDirPath}/**/*.ts`);
57-
files = allFiles.map(createSourceFile);
56+
const allFiles = glob(`${fileOrDirPath}/**/*.ts`);
57+
for await (const file of allFiles) {
58+
files.push(createSourceFile(file));
59+
}
5860
} else {
5961
files = [createSourceFile(fileOrDirPath)];
6062
const maybeTestFile = await getTestFilePath(fileOrDirPath);
@@ -67,7 +69,11 @@ export async function registerZonelessMigrationTool(
6769
const content = sourceFile.getFullText();
6870
const componentSpecifier = getImportSpecifier(sourceFile, '@angular/core', 'Component');
6971
const zoneSpecifier = getImportSpecifier(sourceFile, '@angular/core', 'NgZone');
70-
const testBedSpecifier = getImportSpecifier(sourceFile, '@angular/core/testing', 'TestBed');
72+
const testBedSpecifier = getImportSpecifier(
73+
sourceFile,
74+
/(@angular\/core)?\/testing/,
75+
'TestBed',
76+
);
7177
if (testBedSpecifier) {
7278
componentTestFiles.add(sourceFile);
7379
} else if (componentSpecifier) {

0 commit comments

Comments
 (0)