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-template', 'API_KEY:API key:true', '--env-template', 'BASE_URL:Base URL:false', ], { 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")'], envTemplate: [ { name: 'API_KEY', description: 'API key', isSecret: true }, { name: 'BASE_URL', description: 'Base URL', isSecret: false }, ], }); }); 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 profile', () => { it('creates a profile resolving server name', async () => { vi.mocked(client.get).mockResolvedValue([ { id: 'srv-abc', name: 'ha-mcp' }, ]); const cmd = createCreateCommand({ client, log }); await cmd.parseAsync(['profile', 'production', '--server', 'ha-mcp'], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/profiles', expect.objectContaining({ name: 'production', serverId: 'srv-abc', })); }); it('parses --env KEY=value entries', async () => { vi.mocked(client.get).mockResolvedValue([ { id: 'srv-1', name: 'test' }, ]); const cmd = createCreateCommand({ client, log }); await cmd.parseAsync([ 'profile', 'dev', '--server', 'test', '--env', 'FOO=bar', '--env', 'SECRET=s3cr3t', ], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/profiles', expect.objectContaining({ envOverrides: { FOO: 'bar', SECRET: 's3cr3t' }, })); }); it('passes permissions', async () => { vi.mocked(client.get).mockResolvedValue([ { id: 'srv-1', name: 'test' }, ]); const cmd = createCreateCommand({ client, log }); await cmd.parseAsync([ 'profile', 'admin', '--server', 'test', '--permissions', 'read', '--permissions', 'write', ], { from: 'user' }); expect(client.post).toHaveBeenCalledWith('/api/v1/profiles', expect.objectContaining({ permissions: ['read', 'write'], })); }); }); 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: '', }); }); }); });