import { describe, it, expect, vi, beforeEach } from 'vitest'; import { createCreateCommand } from '../../src/commands/create.js'; import type { ApiClient } from '../../src/api-client.js'; function mockClient(): ApiClient { return { get: vi.fn(async () => []), post: vi.fn(async () => ({ id: 'new-id', name: 'test' })), put: vi.fn(async () => ({})), delete: vi.fn(async () => {}), } as unknown as ApiClient; } describe('create command', () => { let client: ReturnType; let output: string[]; const log = (...args: unknown[]) => output.push(args.map(String).join(' ')); beforeEach(() => { client = mockClient(); output = []; }); describe('create server', () => { it('creates a server with minimal flags', async () => { const cmd = createCreateCommand({ client, log }); await cmd.parseAsync(['server', 'my-server'], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/servers', expect.objectContaining({ name: 'my-server', transport: 'STDIO', replicas: 1, })); expect(output.join('\n')).toContain("server 'test' created"); }); it('creates a server with all flags', async () => { const cmd = createCreateCommand({ client, log }); await cmd.parseAsync([ 'server', 'ha-mcp', '-d', 'Home Assistant MCP', '--docker-image', 'ghcr.io/ha-mcp:latest', '--transport', 'STREAMABLE_HTTP', '--external-url', 'http://localhost:8086/mcp', '--container-port', '3000', '--replicas', '2', '--command', 'python', '--command', '-c', '--command', 'print("hello")', '--env', 'API_KEY=secretRef:creds:API_KEY', '--env', 'BASE_URL=http://localhost', ], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/servers', { name: 'ha-mcp', description: 'Home Assistant MCP', dockerImage: 'ghcr.io/ha-mcp:latest', transport: 'STREAMABLE_HTTP', externalUrl: 'http://localhost:8086/mcp', containerPort: 3000, replicas: 2, command: ['python', '-c', 'print("hello")'], env: [ { name: 'API_KEY', valueFrom: { secretRef: { name: 'creds', key: 'API_KEY' } } }, { name: 'BASE_URL', value: 'http://localhost' }, ], }); }); it('defaults transport to STDIO', async () => { const cmd = createCreateCommand({ client, log }); await cmd.parseAsync(['server', 'test'], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/servers', expect.objectContaining({ transport: 'STDIO', })); }); }); describe('create secret', () => { it('creates a secret with --data flags', async () => { const cmd = createCreateCommand({ client, log }); await cmd.parseAsync([ 'secret', 'ha-creds', '--data', 'TOKEN=abc123', '--data', 'URL=https://ha.local', ], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/secrets', { name: 'ha-creds', data: { TOKEN: 'abc123', URL: 'https://ha.local' }, }); expect(output.join('\n')).toContain("secret 'test' created"); }); it('creates a secret with empty data', async () => { const cmd = createCreateCommand({ client, log }); await cmd.parseAsync(['secret', 'empty-secret'], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/secrets', { name: 'empty-secret', data: {}, }); }); }); describe('create project', () => { it('creates a project', async () => { const cmd = createCreateCommand({ client, log }); await cmd.parseAsync(['project', 'my-project', '-d', 'A test project'], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/projects', { name: 'my-project', description: 'A test project', }); expect(output.join('\n')).toContain("project 'test' created"); }); it('creates a project with no description', async () => { const cmd = createCreateCommand({ client, log }); await cmd.parseAsync(['project', 'minimal'], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/projects', { name: 'minimal', description: '', }); }); }); });