Files
mcpctl/src/mcpd/tests/validation.test.ts
Michal 6d9a9f572c feat: replace profiles with kubernetes-style secrets
Replace the confused Profile abstraction with a dedicated Secret resource
following Kubernetes conventions. Servers now have env entries with inline
values or secretRef references. Env vars are resolved and passed to
containers at startup (fixes existing gap).

- Add Secret CRUD (model, repo, service, routes, CLI commands)
- Server env: {name, value} or {name, valueFrom: {secretRef: {name, key}}}
- Add env-resolver utility shared by instance startup and config generation
- Remove all profile-related code (models, services, routes, CLI, tests)
- Update backup/restore for secrets instead of profiles
- describe secret masks values by default, --show-values to reveal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:40:58 +00:00

104 lines
3.1 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import {
CreateMcpServerSchema,
UpdateMcpServerSchema,
} from '../src/validation/index.js';
describe('CreateMcpServerSchema', () => {
it('validates valid input', () => {
const result = CreateMcpServerSchema.parse({
name: 'my-server',
description: 'A test server',
transport: 'STDIO',
});
expect(result.name).toBe('my-server');
expect(result.env).toEqual([]);
});
it('rejects empty name', () => {
expect(() => CreateMcpServerSchema.parse({ name: '' })).toThrow();
});
it('rejects name with spaces', () => {
expect(() => CreateMcpServerSchema.parse({ name: 'my server' })).toThrow();
});
it('rejects uppercase name', () => {
expect(() => CreateMcpServerSchema.parse({ name: 'MyServer' })).toThrow();
});
it('allows hyphens in name', () => {
const result = CreateMcpServerSchema.parse({ name: 'my-mcp-server' });
expect(result.name).toBe('my-mcp-server');
});
it('defaults transport to STDIO', () => {
const result = CreateMcpServerSchema.parse({ name: 'test' });
expect(result.transport).toBe('STDIO');
});
it('validates env entries with inline value', () => {
const result = CreateMcpServerSchema.parse({
name: 'test',
env: [
{ name: 'API_URL', value: 'https://example.com' },
],
});
expect(result.env).toHaveLength(1);
expect(result.env[0]?.value).toBe('https://example.com');
});
it('validates env entries with secretRef', () => {
const result = CreateMcpServerSchema.parse({
name: 'test',
env: [
{ name: 'API_KEY', valueFrom: { secretRef: { name: 'my-secret', key: 'api-key' } } },
],
});
expect(result.env).toHaveLength(1);
expect(result.env[0]?.valueFrom?.secretRef.name).toBe('my-secret');
});
it('rejects env entry with neither value nor valueFrom', () => {
expect(() => CreateMcpServerSchema.parse({
name: 'test',
env: [{ name: 'FOO' }],
})).toThrow();
});
it('rejects env entry with both value and valueFrom', () => {
expect(() => CreateMcpServerSchema.parse({
name: 'test',
env: [{ name: 'FOO', value: 'bar', valueFrom: { secretRef: { name: 'x', key: 'y' } } }],
})).toThrow();
});
it('rejects invalid transport', () => {
expect(() => CreateMcpServerSchema.parse({ name: 'test', transport: 'HTTP' })).toThrow();
});
it('rejects invalid repository URL', () => {
expect(() => CreateMcpServerSchema.parse({ name: 'test', repositoryUrl: 'not-a-url' })).toThrow();
});
});
describe('UpdateMcpServerSchema', () => {
it('allows partial updates', () => {
const result = UpdateMcpServerSchema.parse({ description: 'updated' });
expect(result.description).toBe('updated');
expect(result.transport).toBeUndefined();
});
it('allows empty object', () => {
const result = UpdateMcpServerSchema.parse({});
expect(Object.keys(result)).toHaveLength(0);
});
it('allows nullable fields', () => {
const result = UpdateMcpServerSchema.parse({ packageName: null, dockerImage: null });
expect(result.packageName).toBeNull();
expect(result.dockerImage).toBeNull();
});
});