import { describe, it, expect } from 'vitest'; import { deduplicateResults } from '../../src/registry/dedup.js'; import type { RegistryServer } from '../../src/registry/types.js'; function makeServer(overrides: Partial = {}): RegistryServer { return { name: 'test-server', description: 'A test server', packages: {}, envTemplate: [], transport: 'stdio', popularityScore: 0, verified: false, sourceRegistry: 'official', ...overrides, }; } describe('deduplicateResults', () => { it('keeps unique servers', () => { const servers = [ makeServer({ name: 'server-a', packages: { npm: 'pkg-a' } }), makeServer({ name: 'server-b', packages: { npm: 'pkg-b' } }), ]; expect(deduplicateResults(servers)).toHaveLength(2); }); it('deduplicates by npm package name, keeps higher popularity', () => { const servers = [ makeServer({ name: 'low', packages: { npm: '@test/slack' }, popularityScore: 10, sourceRegistry: 'official' }), makeServer({ name: 'high', packages: { npm: '@test/slack' }, popularityScore: 100, sourceRegistry: 'smithery' }), ]; const result = deduplicateResults(servers); expect(result).toHaveLength(1); expect(result[0]?.name).toBe('high'); expect(result[0]?.popularityScore).toBe(100); }); it('deduplicates by GitHub URL with different formats', () => { const servers = [ makeServer({ name: 'a', repositoryUrl: 'https://github.com/org/repo', popularityScore: 5 }), makeServer({ name: 'b', repositoryUrl: 'git@github.com:org/repo.git', popularityScore: 50 }), ]; const result = deduplicateResults(servers); expect(result).toHaveLength(1); expect(result[0]?.name).toBe('b'); }); it('merges envTemplate from both sources', () => { const servers = [ makeServer({ name: 'a', packages: { npm: 'pkg' }, envTemplate: [{ name: 'TOKEN', description: 'API token', isSecret: true }], popularityScore: 10, }), makeServer({ name: 'b', packages: { npm: 'pkg' }, envTemplate: [{ name: 'URL', description: 'Base URL', isSecret: false }], popularityScore: 5, }), ]; const result = deduplicateResults(servers); expect(result).toHaveLength(1); expect(result[0]?.envTemplate).toHaveLength(2); expect(result[0]?.envTemplate.map((e) => e.name)).toContain('TOKEN'); expect(result[0]?.envTemplate.map((e) => e.name)).toContain('URL'); }); it('deduplicates envTemplate by var name', () => { const servers = [ makeServer({ packages: { npm: 'pkg' }, envTemplate: [{ name: 'TOKEN', description: 'from a', isSecret: true }], popularityScore: 10, }), makeServer({ packages: { npm: 'pkg' }, envTemplate: [{ name: 'TOKEN', description: 'from b', isSecret: true }], popularityScore: 5, }), ]; const result = deduplicateResults(servers); expect(result[0]?.envTemplate).toHaveLength(1); }); it('merges verified status (OR)', () => { const servers = [ makeServer({ packages: { npm: 'pkg' }, verified: true, popularityScore: 10 }), makeServer({ packages: { npm: 'pkg' }, verified: false, popularityScore: 5 }), ]; const result = deduplicateResults(servers); expect(result[0]?.verified).toBe(true); }); it('handles servers with no npm or repo', () => { const servers = [ makeServer({ name: 'a' }), makeServer({ name: 'b' }), ]; // No matching key → no dedup expect(deduplicateResults(servers)).toHaveLength(2); }); });