open-design/apps/daemon/tests/mcp-resolve-project.test.ts
marco 5dd70b5016
Some checks failed
ci / Validate workspace (push) Successful in 12m32s
landing-page-ci / Validate landing page (push) Successful in 9m41s
landing-page-deploy / Deploy landing page (push) Failing after 5m23s
github-metrics / Generate repository metrics SVG (push) Failing after 2m3s
refresh-contributors-wall / Refresh contributors wall cache bust (push) Failing after 11s
Initial import: open-design source for helix-mind.ai distribution
This repository contains the open-design daemon CLI source code, built
and packaged at https://helix-mind.ai/cli/open-design/latest.tgz for use
by the HelixMind /design slash command.

Licenses: Apache-2.0 (root) + MIT (skills/*)
2026-05-06 20:50:24 +02:00

89 lines
3.4 KiB
TypeScript

// @ts-nocheck
import http from 'node:http';
import express from 'express';
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { resolveProjectId, withActiveEcho } from '../src/mcp.js';
// Two projects whose names share the substring 'app' for ambiguity testing.
const PROJECTS = [
{ id: '11111111-1111-1111-1111-111111111111', name: 'My App' },
{ id: '22222222-2222-2222-2222-222222222222', name: 'Store App' },
{ id: '33333333-3333-3333-3333-333333333333', name: 'recaptr' },
];
describe('resolveProjectId', () => {
let server;
let baseUrl;
beforeAll(
() =>
new Promise((resolve) => {
const app = express();
app.get('/api/projects', (_req, res) => res.json({ projects: PROJECTS }));
const tmp = http.createServer();
tmp.listen(0, '127.0.0.1', () => {
const { port } = tmp.address();
baseUrl = `http://127.0.0.1:${port}`;
tmp.close(() => {
server = app.listen(port, '127.0.0.1', () => resolve());
});
});
}),
);
afterAll(() => new Promise((resolve) => server.close(resolve)));
it('UUID input returns source: uuid without fetching the project list', async () => {
const r = await resolveProjectId(baseUrl, '11111111-1111-1111-1111-111111111111');
expect(r.source).toBe('uuid');
expect(r.id).toBe('11111111-1111-1111-1111-111111111111');
});
it('exact name match returns source: exact', async () => {
const r = await resolveProjectId(baseUrl, 'My App');
expect(r.source).toBe('exact');
expect(r.id).toBe('11111111-1111-1111-1111-111111111111');
expect(r.name).toBe('My App');
});
it('slug match (my-app) returns source: slug', async () => {
const r = await resolveProjectId(baseUrl, 'my-app');
expect(r.source).toBe('slug');
expect(r.id).toBe('11111111-1111-1111-1111-111111111111');
});
it('single substring match returns source: substring', async () => {
const r = await resolveProjectId(baseUrl, 'recapt');
expect(r.source).toBe('substring');
expect(r.id).toBe('33333333-3333-3333-3333-333333333333');
expect(r.name).toBe('recaptr');
});
it('multiple substring matches throw an ambiguity error', async () => {
// 'My App' and 'Store App' both contain 'app'
await expect(resolveProjectId(baseUrl, 'app')).rejects.toThrow(/multiple projects match/);
});
});
describe('withActiveEcho resolvedProject stamping', () => {
it('uuid source: resolvedProject is not added', () => {
const result = withActiveEcho({ x: 1 }, null, { id: 'abc', name: 'Test', source: 'uuid' });
expect(result).not.toHaveProperty('resolvedProject');
});
it('exact source: resolvedProject is not added', () => {
const result = withActiveEcho({ x: 1 }, null, { id: 'abc', name: 'Test', source: 'exact' });
expect(result).not.toHaveProperty('resolvedProject');
});
it('slug source: resolvedProject is added with id and name', () => {
const result = withActiveEcho({ x: 1 }, null, { id: 'abc', name: 'Test', source: 'slug' });
expect(result.resolvedProject).toEqual({ id: 'abc', name: 'Test' });
});
it('substring source: resolvedProject is added with id and name', () => {
const result = withActiveEcho({ x: 1 }, null, { id: 'abc', name: 'Test', source: 'substring' });
expect(result.resolvedProject).toEqual({ id: 'abc', name: 'Test' });
});
});