Files
mcpctl/src/cli/tests/registry/ranking.test.ts

92 lines
2.8 KiB
TypeScript
Raw Normal View History

import { describe, it, expect } from 'vitest';
import { rankResults } from '../../src/registry/ranking.js';
import type { RegistryServer } from '../../src/registry/types.js';
function makeServer(overrides: Partial<RegistryServer> = {}): RegistryServer {
return {
name: 'test-server',
description: 'A test server',
packages: {},
envTemplate: [],
transport: 'stdio',
popularityScore: 0,
verified: false,
sourceRegistry: 'official',
...overrides,
};
}
describe('rankResults', () => {
it('puts exact name match first', () => {
const servers = [
makeServer({ name: 'slack-extended-tools' }),
makeServer({ name: 'slack' }),
makeServer({ name: 'my-slack-bot' }),
];
const ranked = rankResults(servers, 'slack');
expect(ranked[0]?.name).toBe('slack');
});
it('ranks verified servers higher than unverified', () => {
const servers = [
makeServer({ name: 'server-a', verified: false }),
makeServer({ name: 'server-b', verified: true }),
];
const ranked = rankResults(servers, 'server');
expect(ranked[0]?.name).toBe('server-b');
});
it('ranks popular servers higher', () => {
const servers = [
makeServer({ name: 'unpopular', popularityScore: 1 }),
makeServer({ name: 'popular', popularityScore: 10000 }),
];
const ranked = rankResults(servers, 'test');
expect(ranked[0]?.name).toBe('popular');
});
it('considers recency', () => {
const recent = new Date();
const old = new Date(Date.now() - 365 * 24 * 60 * 60 * 1000);
const servers = [
makeServer({ name: 'old-server', lastUpdated: old }),
makeServer({ name: 'new-server', lastUpdated: recent }),
];
const ranked = rankResults(servers, 'test');
expect(ranked[0]?.name).toBe('new-server');
});
it('handles missing lastUpdated gracefully', () => {
const servers = [
makeServer({ name: 'no-date' }),
makeServer({ name: 'has-date', lastUpdated: new Date() }),
];
// Should not throw
const ranked = rankResults(servers, 'test');
expect(ranked).toHaveLength(2);
});
it('produces stable ordering for identical scores', () => {
const servers = Array.from({ length: 10 }, (_, i) =>
makeServer({ name: `server-${String(i)}` }),
);
const ranked1 = rankResults(servers, 'test');
const ranked2 = rankResults(servers, 'test');
expect(ranked1.map((s) => s.name)).toEqual(ranked2.map((s) => s.name));
});
it('returns empty array for empty input', () => {
expect(rankResults([], 'test')).toEqual([]);
});
it('does not mutate original array', () => {
const servers = [
makeServer({ name: 'b' }),
makeServer({ name: 'a' }),
];
const original = [...servers];
rankResults(servers, 'test');
expect(servers.map((s) => s.name)).toEqual(original.map((s) => s.name));
});
});