@yeepay/awesome-components-mcp
Version:
MCP server providing access to awesome-components documentation and integration guides with dual-mode operation: direct fetch and GitLab MCP instruction generation
200 lines (197 loc) • 9.64 kB
JavaScript
;
/**
* Unit tests for Components Discovery Tool
*/
Object.defineProperty(exports, "__esModule", { value: true });
const componentsDiscovery_1 = require("../tools/componentsDiscovery");
const gitlabClient_1 = require("../services/gitlabClient");
// Mock the GitLab client
jest.mock('../services/gitlabClient', () => ({
fetchGitLabFileContentSafe: jest.fn(),
GitLabError: class GitLabError extends Error {
statusCode;
url;
constructor(message, statusCode, url) {
super(message);
this.statusCode = statusCode;
this.url = url;
this.name = 'GitLabError';
}
}
}));
// Mock the config
jest.mock('../config', () => ({
config: {
urls: {
mainLlms: 'https://gitlab.example.com/repo/-/raw/main/llms.txt'
}
}
}));
const gitlabClient_2 = require("../services/gitlabClient");
const mockFetchGitLabFileContentSafe = gitlabClient_2.fetchGitLabFileContentSafe;
describe('Components Discovery Tool', () => {
beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(console, 'log').mockImplementation(() => { });
jest.spyOn(console, 'error').mockImplementation(() => { });
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('parseLlmsContent', () => {
it('should parse basic component list', () => {
const content = `# Awesome Components
component-a
component-b
guide/getting-started
docs/readme.md`;
const result = (0, componentsDiscovery_1.parseLlmsContent)(content);
expect(result.title).toBe('Awesome Components');
expect(result.totalComponents).toBe(4);
expect(result.components).toHaveLength(4);
expect(result.components[0].name).toBe('component-a');
expect(result.components[1].name).toBe('component-b');
expect(result.components[2].name).toBe('guide/getting-started');
expect(result.components[2].type).toBe('guide');
expect(result.components[3].name).toBe('docs/readme.md');
expect(result.components[3].type).toBe('documentation');
});
it('should handle empty content', () => {
const result = (0, componentsDiscovery_1.parseLlmsContent)('');
expect(result.totalComponents).toBe(0);
expect(result.components).toHaveLength(0);
});
it('should skip comments and headers', () => {
const content = `# Title
// This is a comment
<!-- HTML comment -->
component-a
# Another header
component-b`;
const result = (0, componentsDiscovery_1.parseLlmsContent)(content);
expect(result.totalComponents).toBe(2);
expect(result.components[0].name).toBe('component-a');
expect(result.components[1].name).toBe('component-b');
});
it('should detect component types correctly', () => {
const content = `button-component
tutorial-guide
documentation.md
other-item`;
const result = (0, componentsDiscovery_1.parseLlmsContent)(content);
expect(result.components[0].type).toBe('component');
expect(result.components[1].type).toBe('guide');
expect(result.components[2].type).toBe('documentation');
expect(result.components[3].type).toBe('other');
});
it('should extract paths for file-like entries', () => {
const content = `components/button.tsx
guides/getting-started.md
simple-name`;
const result = (0, componentsDiscovery_1.parseLlmsContent)(content);
expect(result.components[0].path).toBe('components/button.tsx');
expect(result.components[1].path).toBe('guides/getting-started.md');
expect(result.components[2].path).toBeUndefined();
});
});
describe('generateComponentsSummary', () => {
it('should generate summary for components', () => {
const parsed = {
title: 'Test Components',
totalComponents: 3,
components: [
{ name: 'button', type: 'component' },
{ name: 'guide', type: 'guide' },
{ name: 'docs', type: 'documentation' }
]
};
const summary = (0, componentsDiscovery_1.generateComponentsSummary)(parsed);
expect(summary).toContain('Test Components');
expect(summary).toContain('Total Components Found: 3');
expect(summary).toContain('component: 1 items');
expect(summary).toContain('guide: 1 items');
expect(summary).toContain('documentation: 1 items');
expect(summary).toContain('1. button (component)');
});
it('should handle empty component list', () => {
const parsed = {
totalComponents: 0,
components: []
};
const summary = (0, componentsDiscovery_1.generateComponentsSummary)(parsed);
expect(summary).toContain('Total Components Found: 0');
expect(summary).toContain('No components were found');
});
it('should truncate long component lists', () => {
const components = Array.from({ length: 15 }, (_, i) => ({
name: `component-${i}`,
type: 'component'
}));
const parsed = {
totalComponents: 15,
components
};
const summary = (0, componentsDiscovery_1.generateComponentsSummary)(parsed);
expect(summary).toContain('Total Components Found: 15');
expect(summary).toContain('... and 5 more components');
});
});
describe('componentsDiscoveryTool', () => {
const mockContent = `# Awesome Components
button-component
input-component
guide/getting-started`;
it('should return raw content when format is raw', async () => {
mockFetchGitLabFileContentSafe.mockResolvedValueOnce(mockContent);
const result = await (0, componentsDiscovery_1.componentsDiscoveryTool)({ format: 'raw' });
expect(result.content[0].text).toContain('Raw llms.txt Content');
expect(result.content[0].text).toContain(mockContent);
expect(result.isError).toBeUndefined();
});
it('should return parsed content when format is parsed', async () => {
mockFetchGitLabFileContentSafe.mockResolvedValueOnce(mockContent);
const result = await (0, componentsDiscovery_1.componentsDiscoveryTool)({ format: 'parsed' });
expect(result.content[0].text).toContain('Parsed Components Information');
expect(result.content[0].text).toContain('"totalComponents": 3');
expect(result.content[0].text).toContain('button-component');
expect(result.isError).toBeUndefined();
});
it('should return summary when format is summary', async () => {
mockFetchGitLabFileContentSafe.mockResolvedValueOnce(mockContent);
const result = await (0, componentsDiscovery_1.componentsDiscoveryTool)({ format: 'summary' });
expect(result.content[0].text).toContain('Awesome Components');
expect(result.content[0].text).toContain('Total Components Found: 3');
expect(result.content[0].text).toContain('button-component');
expect(result.isError).toBeUndefined();
});
it('should default to parsed format when no format specified', async () => {
mockFetchGitLabFileContentSafe.mockResolvedValueOnce(mockContent);
const result = await (0, componentsDiscovery_1.componentsDiscoveryTool)({ format: 'parsed' });
expect(result.content[0].text).toContain('Components Discovery Results');
expect(result.content[0].text).toContain('"totalComponents": 3');
expect(result.isError).toBeUndefined();
});
it('should handle GitLab errors gracefully', async () => {
const gitlabError = new gitlabClient_1.GitLabError('File not found', 404, 'https://example.com/file.txt');
mockFetchGitLabFileContentSafe.mockRejectedValueOnce(gitlabError);
const result = await (0, componentsDiscovery_1.componentsDiscoveryTool)({ format: 'summary' });
expect(result.content[0].text).toContain('Error: Components Discovery Failed');
expect(result.content[0].text).toContain('GitLab Error: File not found');
expect(result.content[0].text).toContain('Status Code: 404');
expect(result.isError).toBe(true);
});
it('should handle general errors gracefully', async () => {
mockFetchGitLabFileContentSafe.mockRejectedValueOnce(new Error('Network error'));
const result = await (0, componentsDiscovery_1.componentsDiscoveryTool)({ format: 'summary' });
expect(result.content[0].text).toContain('Error: Components Discovery Failed');
expect(result.content[0].text).toContain('Error: Network error');
expect(result.isError).toBe(true);
});
it('should log the fetch URL', async () => {
const consoleSpy = jest.spyOn(console, 'log');
mockFetchGitLabFileContentSafe.mockResolvedValueOnce(mockContent);
await (0, componentsDiscovery_1.componentsDiscoveryTool)({ format: 'summary' });
expect(consoleSpy).toHaveBeenCalledWith('Fetching components list from: https://gitlab.example.com/repo/-/raw/main/llms.txt');
});
});
});