a46764fb1b
ci / Validate workspace (push) Has been cancelled
landing-page-ci / Validate landing page (push) Has been cancelled
landing-page-deploy / Deploy landing page (push) Has been cancelled
github-metrics / Generate repository metrics SVG (push) Has been cancelled
refresh-contributors-wall / Refresh contributors wall cache bust (push) Waiting to run
89 lines
3.3 KiB
TypeScript
89 lines
3.3 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' });
|
|
});
|
|
});
|