lobehub/apps/cli/src/tools/shell.test.ts
Arvin Xu 860e11ab3a
♻️ refactor(cli): extract shared @lobechat/local-file-shell package (#12865)
* ♻️ refactor(cli): extract shared @lobechat/local-file-shell package

Extract common file and shell operations from Desktop and CLI into a
shared package to eliminate ~1500 lines of duplicated code. CLI now
uses @lobechat/file-loaders for rich format support (PDF, DOCX, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* update

* update commands

* update version

* update deps

* refactor version issue

*  feat(local-file-shell): add cwd support, move/rename ops, improve logging

- Add missing `cwd` parameter to `runCommand` (align with Desktop)
- Add `moveLocalFiles` with batch support and detailed error handling
- Add `renameLocalFile` with path validation and traversal prevention
- Add error logging in shell runner's error/completion handlers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* support update model and provider in cli

* fix desktop build

* fix

* 🐛 fix: pin fast-xml-parser to 5.4.2 in bun overrides

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:04:22 +08:00

65 lines
1.9 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest';
import { cleanupAllProcesses, getCommandOutput, killCommand, runCommand } from './shell';
vi.mock('../utils/logger', () => ({
log: {
debug: vi.fn(),
error: vi.fn(),
info: vi.fn(),
warn: vi.fn(),
},
}));
describe('shell tools (integration wrapper)', () => {
afterEach(() => {
cleanupAllProcesses();
});
it('should delegate runCommand to shared package', async () => {
const result = await runCommand({ command: 'echo hello' });
expect(result.success).toBe(true);
expect(result.stdout).toContain('hello');
});
it('should delegate background commands and getCommandOutput', async () => {
const bgResult = await runCommand({
command: 'echo background && sleep 0.1',
run_in_background: true,
});
expect(bgResult.success).toBe(true);
expect(bgResult.shell_id).toBeDefined();
await new Promise((r) => setTimeout(r, 200));
const output = await getCommandOutput({ shell_id: bgResult.shell_id! });
expect(output.success).toBe(true);
expect(output.stdout).toContain('background');
});
it('should delegate killCommand', async () => {
const bgResult = await runCommand({
command: 'sleep 60',
run_in_background: true,
});
const result = await killCommand({ shell_id: bgResult.shell_id! });
expect(result.success).toBe(true);
});
it('should return error for unknown shell_id', async () => {
const result = await getCommandOutput({ shell_id: 'unknown-id' });
expect(result.success).toBe(false);
expect(result.error).toContain('not found');
});
it('should cleanup all processes', async () => {
await runCommand({ command: 'sleep 60', run_in_background: true });
await runCommand({ command: 'sleep 60', run_in_background: true });
cleanupAllProcesses();
// No assertion needed — verifies no throw
});
});