summaryrefslogtreecommitdiff
path: root/integration-tests
diff options
context:
space:
mode:
authorAbhi <[email protected]>2025-08-17 00:02:54 -0400
committerGitHub <[email protected]>2025-08-17 04:02:54 +0000
commit33b9bdb11e9371dfa6891ba1be47a12b958f493d (patch)
tree46ac192df7dd2aeaf35cb5eef5c121bc5decada9 /integration-tests
parente7dbc607a598c5270507d0ce7d55a3c98dcb0c0c (diff)
feat(cli): Introduce arguments for shell execution in custom commands (#5966)
Diffstat (limited to 'integration-tests')
-rw-r--r--integration-tests/shell-service.test.ts122
1 files changed, 122 insertions, 0 deletions
diff --git a/integration-tests/shell-service.test.ts b/integration-tests/shell-service.test.ts
new file mode 100644
index 00000000..58cf65e5
--- /dev/null
+++ b/integration-tests/shell-service.test.ts
@@ -0,0 +1,122 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { describe, it, expect, beforeAll } from 'vitest';
+import { ShellExecutionService } from '../packages/core/src/services/shellExecutionService.js';
+import * as fs from 'fs/promises';
+import * as path from 'path';
+import { vi } from 'vitest';
+
+describe('ShellExecutionService programmatic integration tests', () => {
+ let testDir: string;
+
+ beforeAll(async () => {
+ // Create a dedicated directory for this test suite to avoid conflicts.
+ testDir = path.join(
+ process.env.INTEGRATION_TEST_FILE_DIR!,
+ 'shell-service-tests',
+ );
+ await fs.mkdir(testDir, { recursive: true });
+ });
+
+ it('should execute a simple cross-platform command (echo)', async () => {
+ const command = 'echo "hello from the service"';
+ const onOutputEvent = vi.fn();
+ const abortController = new AbortController();
+
+ const handle = ShellExecutionService.execute(
+ command,
+ testDir,
+ onOutputEvent,
+ abortController.signal,
+ );
+
+ const result = await handle.result;
+
+ expect(result.error).toBeNull();
+ expect(result.exitCode).toBe(0);
+ // Output can vary slightly between shells (e.g., quotes), so check for inclusion.
+ expect(result.output).toContain('hello from the service');
+ });
+
+ it.runIf(process.platform === 'win32')(
+ 'should execute "dir" on Windows',
+ async () => {
+ const testFile = 'test-file-windows.txt';
+ await fs.writeFile(path.join(testDir, testFile), 'windows test');
+
+ const command = 'dir';
+ const onOutputEvent = vi.fn();
+ const abortController = new AbortController();
+
+ const handle = ShellExecutionService.execute(
+ command,
+ testDir,
+ onOutputEvent,
+ abortController.signal,
+ );
+
+ const result = await handle.result;
+
+ expect(result.error).toBeNull();
+ expect(result.exitCode).toBe(0);
+ expect(result.output).toContain(testFile);
+ },
+ );
+
+ it.skipIf(process.platform === 'win32')(
+ 'should execute "ls -l" on Unix',
+ async () => {
+ const testFile = 'test-file-unix.txt';
+ await fs.writeFile(path.join(testDir, testFile), 'unix test');
+
+ const command = 'ls -l';
+ const onOutputEvent = vi.fn();
+ const abortController = new AbortController();
+
+ const handle = ShellExecutionService.execute(
+ command,
+ testDir,
+ onOutputEvent,
+ abortController.signal,
+ );
+
+ const result = await handle.result;
+
+ expect(result.error).toBeNull();
+ expect(result.exitCode).toBe(0);
+ expect(result.output).toContain(testFile);
+ },
+ );
+
+ it('should abort a running process', async () => {
+ // A command that runs for a bit. 'sleep' on unix, 'timeout' on windows.
+ const command = process.platform === 'win32' ? 'timeout /t 20' : 'sleep 20';
+ const onOutputEvent = vi.fn();
+ const abortController = new AbortController();
+
+ const handle = ShellExecutionService.execute(
+ command,
+ testDir,
+ onOutputEvent,
+ abortController.signal,
+ );
+
+ // Abort shortly after starting
+ setTimeout(() => abortController.abort(), 50);
+
+ const result = await handle.result;
+
+ // For debugging the flaky test.
+ console.log('Abort test result:', result);
+
+ expect(result.aborted).toBe(true);
+ // A clean exit is exitCode 0 and no signal. If the process was truly
+ // aborted, it should not have exited cleanly.
+ const exitedCleanly = result.exitCode === 0 && result.signal === null;
+ expect(exitedCleanly, 'Process should not have exited cleanly').toBe(false);
+ });
+});