Skip to content

Commit a28a57d

Browse files
cameroncookeclaude
andcommitted
test(smoke-tests): Harden CLI invocation and teardown assertions
Use execFileSync for CLI smoke invocations to avoid shell-string execution and satisfy code scanning feedback. Require non-empty output in the --output json smoke test even when the tool exits non-zero on non-macOS. Guard harness cleanup in doctor and scaffolding suites so setup failures do not mask root causes. Use distinctive session defaults in clear-defaults assertions to avoid fragile substring matches. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2ffbeb0 commit a28a57d

4 files changed

Lines changed: 13 additions & 10 deletions

File tree

src/smoke-tests/__tests__/cli-surface.test.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, it, expect } from 'vitest';
2-
import { execSync } from 'child_process';
2+
import { execFileSync } from 'child_process';
33
import { resolve } from 'path';
44

55
const CLI = resolve(__dirname, '../../../build/cli.js');
@@ -11,7 +11,8 @@ const cliEnv = (() => {
1111
return env;
1212
})();
1313
const run = (args: string): string => {
14-
return execSync(`node ${CLI} ${args}`, {
14+
const argv = args.trim() ? args.trim().split(/\s+/) : [];
15+
return execFileSync('node', [CLI, ...argv], {
1516
encoding: 'utf8',
1617
timeout: 15_000,
1718
env: cliEnv,
@@ -108,12 +109,14 @@ describe('CLI Surface (e2e)', () => {
108109
// list_sims is a good candidate -- it will fail to run xcrun but should
109110
// return structured JSON output even on error
110111
const result = runMayFail('simulator list-sims --output json');
111-
// Even if the tool fails (no xcrun), the output format should be JSON
112+
const output = result.stdout.trim();
113+
expect(output.length).toBeGreaterThan(0);
114+
// Even if the tool fails (no xcrun), a successful run should be JSON
112115
if (result.status === 0) {
113-
const parsed = JSON.parse(result.stdout);
116+
const parsed = JSON.parse(output);
114117
expect(parsed).toBeDefined();
115118
}
116-
// If it fails, that's also acceptable on non-macOS platforms
119+
// If it fails, that's acceptable on non-macOS platforms as long as output is present
117120
});
118121

119122
it('missing required args produces user-friendly error', () => {

src/smoke-tests/__tests__/e2e-mcp-doctor.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ beforeAll(async () => {
1313
}, 30_000);
1414

1515
afterAll(async () => {
16-
await harness.cleanup();
16+
await harness?.cleanup();
1717
});
1818

1919
describe('MCP Doctor Tool (e2e)', () => {

src/smoke-tests/__tests__/e2e-mcp-scaffolding.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ beforeAll(async () => {
1111
}, 30_000);
1212

1313
afterAll(async () => {
14-
await harness.cleanup();
14+
await harness?.cleanup();
1515
});
1616

1717
describe('MCP Project Scaffolding Tools (e2e)', () => {

src/smoke-tests/__tests__/e2e-mcp-sessions.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ describe('MCP Session Management (e2e)', () => {
7373
// Set defaults
7474
await harness.client.callTool({
7575
name: 'session_set_defaults',
76-
arguments: { scheme: 'App', projectPath: '/proj' },
76+
arguments: { scheme: 'ClearMeScheme', projectPath: '/clear-me-proj' },
7777
});
7878

7979
// Clear all
@@ -90,8 +90,8 @@ describe('MCP Session Management (e2e)', () => {
9090

9191
const text = extractText(result);
9292
// Should not contain the previously set values
93-
expect(text).not.toContain('App');
94-
expect(text).not.toContain('/proj');
93+
expect(text).not.toContain('ClearMeScheme');
94+
expect(text).not.toContain('/clear-me-proj');
9595
});
9696

9797
it('session_clear_defaults clears specific keys', async () => {

0 commit comments

Comments
 (0)