feat(smartshell): add cwd-aware execution options, structured strict-mode errors, and safer process tree termination

This commit is contained in:
2026-05-09 13:48:16 +00:00
parent e61b352576
commit d65e1ed4f6
17 changed files with 3830 additions and 4812 deletions
+34 -6
View File
@@ -1,6 +1,8 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as smartshell from '../ts/index.js';
const getErrorMessage = (error: unknown): string => error instanceof Error ? error.message : String(error);
tap.test('should handle EPIPE errors gracefully', async () => {
const testSmartshell = new smartshell.Smartshell({
executor: 'bash',
@@ -40,7 +42,7 @@ tap.test('should handle strict mode with non-zero exit codes', async () => {
await testSmartshell.execStrict('exit 42');
} catch (error) {
errorThrown = true;
errorMessage = error.message;
errorMessage = getErrorMessage(error);
}
expect(errorThrown).toBeTrue();
@@ -65,13 +67,39 @@ tap.test('should handle strict mode with signal termination', async () => {
await result;
} catch (error) {
errorThrown = true;
errorMessage = error.message;
errorMessage = getErrorMessage(error);
}
expect(errorThrown).toBeTrue();
expect(errorMessage).toContain('terminated by signal');
});
tap.test('strict mode errors should expose command result details', async () => {
const testSmartshell = new smartshell.Smartshell({
executor: 'bash',
sourceFilePaths: [],
});
let caughtError: smartshell.SmartshellError | null = null;
try {
await testSmartshell.execSpawn('bash', ['-c', 'echo stdout-value; echo stderr-value >&2; exit 7'], {
strict: true,
silent: true,
});
} catch (error) {
caughtError = error as smartshell.SmartshellError;
}
expect(caughtError).toBeInstanceOf(smartshell.SmartshellError);
expect(caughtError!.command).toEqual('bash');
expect(caughtError!.exitCode).toEqual(7);
expect(caughtError!.stdout).toContain('stdout-value');
expect(caughtError!.combinedOutput).toContain('stderr-value');
expect(caughtError!.stderr).toContain('stderr-value');
expect(caughtError!.result.exitCode).toEqual(7);
});
tap.test('execAndWaitForLine with timeout should reject properly', async () => {
const testSmartshell = new smartshell.Smartshell({
executor: 'bash',
@@ -90,7 +118,7 @@ tap.test('execAndWaitForLine with timeout should reject properly', async () => {
);
} catch (error) {
errorThrown = true;
errorMessage = error.message;
errorMessage = getErrorMessage(error);
}
expect(errorThrown).toBeTrue();
@@ -133,7 +161,7 @@ tap.test('should handle process ending without matching pattern', async () => {
);
} catch (error) {
errorThrown = true;
errorMessage = error.message;
errorMessage = getErrorMessage(error);
}
expect(errorThrown).toBeTrue();
@@ -169,7 +197,7 @@ tap.test('should handle write after stream destroyed', async () => {
await interactive.sendLine('This should fail');
} catch (error) {
errorThrown = true;
expect(error.message).toContain('destroyed');
expect(getErrorMessage(error)).toContain('destroyed');
}
expect(errorThrown).toBeTrue();
@@ -219,4 +247,4 @@ tap.test('custom environment variables should be passed correctly', async () =>
expect(result.stdout).toContain('test_value_123');
});
export default tap.start();
export default tap.start();