Skip to content

Commit 6664388

Browse files
committed
fix(@angular/cli): use headless option in MCP test tool
This avoids the following error for projects using Vitest and Browser mode: ``` Unhandled Error: Error: [(chrome)] Browser "chrome" is not supported by the browser provider "playwright". Supported browsers: firefox, webkit, chromium. ```
1 parent f1ed025 commit 6664388

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

packages/angular/cli/src/commands/mcp/tools/test.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,16 @@ const testToolOutputSchema = z.object({
2929

3030
export type TestToolOutput = z.infer<typeof testToolOutputSchema>;
3131

32+
function shouldUseHeadlessOption(
33+
testTarget: import('@angular-devkit/core').workspaces.TargetDefinition | undefined,
34+
): boolean {
35+
return (
36+
testTarget?.builder === '@angular/build:unit-test' && testTarget.options?.['runner'] !== 'karma'
37+
);
38+
}
39+
3240
export async function runTest(input: TestToolInput, context: McpToolContext) {
33-
const { workspacePath, projectName } = await resolveWorkspaceAndProject({
41+
const { workspace, workspacePath, projectName } = await resolveWorkspaceAndProject({
3442
host: context.host,
3543
workspacePathInput: input.workspace,
3644
projectNameInput: input.project,
@@ -40,8 +48,13 @@ export async function runTest(input: TestToolInput, context: McpToolContext) {
4048
// Build "ng"'s command line.
4149
const args = ['test', projectName];
4250

43-
// This is ran by the agent so we want a non-watched, headless test.
44-
args.push('--browsers', 'ChromeHeadless');
51+
if (shouldUseHeadlessOption(workspace.projects.get(projectName)?.targets.get('test'))) {
52+
args.push('--headless', 'true');
53+
} else {
54+
// Karma-based projects need an explicit headless browser for non-interactive MCP execution.
55+
args.push('--browsers', 'ChromeHeadless');
56+
}
57+
4558
args.push('--watch', 'false');
4659

4760
if (input.filter) {
@@ -83,7 +96,8 @@ Perform a one-off, non-watched unit test execution with ng test.
8396
<Operational Notes>
8497
* This tool uses "ng test".
8598
* It supports filtering by spec name if the underlying builder supports it (e.g., 'unit-test' builder).
86-
* This runs a headless Chrome as a browser, so requires Chrome to be installed.
99+
* For the "@angular/build:unit-test" builder with Vitest, this tool requests headless execution via "--headless true".
100+
* For Karma-based projects, this tool forces headless Chrome with "--browsers ChromeHeadless", so Chrome must be installed.
87101
</Operational Notes>
88102
`,
89103
isReadOnly: false,

packages/angular/cli/src/commands/mcp/tools/test_spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,40 @@ describe('Test Tool', () => {
9393
expect(structuredContent.status).toBe('failure');
9494
expect(structuredContent.logs).toEqual([...testLogs, 'Test failed']);
9595
});
96+
97+
it('should use the headless option for the unit-test builder when using Vitest', async () => {
98+
addProjectToWorkspace(mockContext.workspace.projects, 'my-vitest-app', {
99+
test: {
100+
builder: '@angular/build:unit-test',
101+
options: {
102+
runner: 'vitest',
103+
},
104+
},
105+
});
106+
107+
await runTest({ project: 'my-vitest-app' }, mockContext);
108+
109+
expect(mockHost.runCommand).toHaveBeenCalledWith(
110+
'ng',
111+
['test', 'my-vitest-app', '--headless', 'true', '--watch', 'false'],
112+
{ cwd: '/test' },
113+
);
114+
});
115+
116+
it('should use the headless option for the unit-test builder when the runner is omitted', async () => {
117+
addProjectToWorkspace(mockContext.workspace.projects, 'my-default-vitest-app', {
118+
test: {
119+
builder: '@angular/build:unit-test',
120+
options: {},
121+
},
122+
});
123+
124+
await runTest({ project: 'my-default-vitest-app' }, mockContext);
125+
126+
expect(mockHost.runCommand).toHaveBeenCalledWith(
127+
'ng',
128+
['test', 'my-default-vitest-app', '--headless', 'true', '--watch', 'false'],
129+
{ cwd: '/test' },
130+
);
131+
});
96132
});

0 commit comments

Comments
 (0)