This commit is contained in:
2026-04-12 01:06:31 +07:00
commit 10d660cbcb
1066 changed files with 228596 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env node
/**
* Test runner - runs all tests
*/
const { spawn } = require('child_process');
const path = require('path');
const tests = [
'test-detect-topic.js',
'test-fetch-docs.js',
'test-analyze-llms.js',
];
let totalPassed = 0;
let totalFailed = 0;
function runTest(testFile) {
return new Promise((resolve, reject) => {
console.log(`\n${'='.repeat(60)}`);
console.log(`Running: ${testFile}`);
console.log('='.repeat(60));
const testPath = path.join(__dirname, testFile);
const proc = spawn('node', [testPath], {
stdio: 'inherit',
});
proc.on('close', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`Test failed: ${testFile}`));
}
});
proc.on('error', reject);
});
}
async function runAllTests() {
console.log('Running all docs-seeker tests...');
let failedTests = [];
for (const test of tests) {
try {
await runTest(test);
} catch (error) {
failedTests.push(test);
}
}
console.log(`\n${'='.repeat(60)}`);
console.log('All Tests Summary');
console.log('='.repeat(60));
console.log(`Total test files: ${tests.length}`);
console.log(`Passed: ${tests.length - failedTests.length}`);
console.log(`Failed: ${failedTests.length}`);
if (failedTests.length > 0) {
console.log('\nFailed tests:');
failedTests.forEach((test) => console.log(` - ${test}`));
process.exit(1);
} else {
console.log('\n✓ All tests passed!');
process.exit(0);
}
}
runAllTests();

View File

@@ -0,0 +1,119 @@
#!/usr/bin/env node
/**
* Tests for analyze-llms-txt.js
*/
const {
analyzeLlmsTxt,
parseUrls,
groupByPriority,
categorizeUrl,
suggestAgentDistribution,
} = require('../analyze-llms-txt');
// Test counter
let passed = 0;
let failed = 0;
function assert(condition, message) {
if (condition) {
console.log(`${message}`);
passed++;
} else {
console.error(`${message}`);
failed++;
}
}
function assertEqual(actual, expected, message) {
if (actual === expected) {
console.log(`${message}`);
passed++;
} else {
console.error(`${message}`);
console.error(` Expected: ${expected}`);
console.error(` Actual: ${actual}`);
failed++;
}
}
console.log('Running analyze-llms-txt.js tests...\n');
// Test categorizeUrl
console.log('## Testing categorizeUrl()');
assertEqual(categorizeUrl('https://docs.example.com/getting-started'), 'critical', 'Categorize getting-started as critical');
assertEqual(categorizeUrl('https://docs.example.com/guide/routing'), 'important', 'Categorize routing guide as important');
assertEqual(categorizeUrl('https://docs.example.com/advanced/internals'), 'supplementary', 'Categorize internals as supplementary');
assertEqual(categorizeUrl('https://docs.example.com/api-reference'), 'important', 'Categorize API reference as important');
// Test parseUrls
console.log('\n## Testing parseUrls()');
const sampleContent = `# Documentation
https://docs.example.com/getting-started
https://docs.example.com/guide
# Comment line
https://docs.example.com/api-reference
https://docs.example.com/advanced
`;
const urls = parseUrls(sampleContent);
assertEqual(urls.length, 4, 'Parse 4 URLs from content');
assert(urls[0].includes('getting-started'), 'First URL is getting-started');
const emptyContent = '';
const emptyUrls = parseUrls(emptyContent);
assertEqual(emptyUrls.length, 0, 'Empty content returns 0 URLs');
// Test groupByPriority
console.log('\n## Testing groupByPriority()');
const testUrls = [
'https://docs.example.com/getting-started',
'https://docs.example.com/guide/routing',
'https://docs.example.com/advanced/internals',
'https://docs.example.com/installation',
];
const grouped = groupByPriority(testUrls);
assert(grouped.critical.length >= 2, 'Has critical URLs');
assert(grouped.important.length >= 1, 'Has important URLs');
assert(grouped.supplementary.length >= 1, 'Has supplementary URLs');
// Test suggestAgentDistribution
console.log('\n## Testing suggestAgentDistribution()');
const dist1 = suggestAgentDistribution(2);
assertEqual(dist1.agentCount, 1, 'Suggest 1 agent for 2 URLs');
assertEqual(dist1.strategy, 'single', 'Strategy is single for few URLs');
const dist2 = suggestAgentDistribution(8);
assert(dist2.agentCount >= 3 && dist2.agentCount <= 5, 'Suggest 3-5 agents for 8 URLs');
assertEqual(dist2.strategy, 'parallel', 'Strategy is parallel for medium URLs');
const dist3 = suggestAgentDistribution(15);
assertEqual(dist3.agentCount, 7, 'Suggest 7 agents for 15 URLs');
const dist4 = suggestAgentDistribution(25);
assertEqual(dist4.agentCount, 7, 'Suggest 7 agents for 25 URLs');
assertEqual(dist4.strategy, 'phased', 'Strategy is phased for many URLs');
assertEqual(dist4.phases, 2, 'Use 2 phases for large sets');
// Test analyzeLlmsTxt
console.log('\n## Testing analyzeLlmsTxt()');
const analysis = analyzeLlmsTxt(sampleContent);
assertEqual(analysis.totalUrls, 4, 'Analysis counts 4 URLs');
assert(analysis.grouped, 'Analysis includes grouped URLs');
assert(analysis.distribution, 'Analysis includes distribution suggestion');
assert(analysis.summary, 'Analysis includes summary');
// Summary
console.log('\n## Test Summary');
console.log(`Passed: ${passed}`);
console.log(`Failed: ${failed}`);
console.log(`Total: ${passed + failed}`);
process.exit(failed > 0 ? 1 : 0);

View File

@@ -0,0 +1,112 @@
#!/usr/bin/env node
/**
* Tests for detect-topic.js
*/
const { detectTopic, normalizeTopic, normalizeLibrary } = require('../detect-topic');
// Test counter
let passed = 0;
let failed = 0;
function assert(condition, message) {
if (condition) {
console.log(`${message}`);
passed++;
} else {
console.error(`${message}`);
failed++;
}
}
function assertEqual(actual, expected, message) {
if (actual === expected) {
console.log(`${message}`);
passed++;
} else {
console.error(`${message}`);
console.error(` Expected: ${expected}`);
console.error(` Actual: ${actual}`);
failed++;
}
}
console.log('Running detect-topic.js tests...\n');
// Test normalizeTopic
console.log('## Testing normalizeTopic()');
assertEqual(normalizeTopic('date picker'), 'date', 'Normalize multi-word topic');
assertEqual(normalizeTopic('OAuth'), 'oauth', 'Normalize OAuth');
assertEqual(normalizeTopic('Server-Side'), 'server', 'Normalize Server-Side');
assertEqual(normalizeTopic('caching'), 'caching', 'Normalize caching');
// Test normalizeLibrary
console.log('\n## Testing normalizeLibrary()');
assertEqual(normalizeLibrary('Next.js'), 'next.js', 'Normalize Next.js');
assertEqual(normalizeLibrary('shadcn/ui'), 'shadcn/ui', 'Normalize shadcn/ui');
assertEqual(normalizeLibrary('Better Auth'), 'better-auth', 'Normalize Better Auth');
// Test topic-specific queries
console.log('\n## Testing topic-specific queries');
const topicQuery1 = detectTopic('How do I use date picker in shadcn/ui?');
assert(topicQuery1 !== null, 'Detect topic-specific query 1');
assert(topicQuery1.isTopicSpecific === true, 'Query 1 is topic-specific');
assertEqual(topicQuery1.topic, 'date', 'Query 1 topic is "date"');
assertEqual(topicQuery1.library, 'shadcn/ui', 'Query 1 library is "shadcn/ui"');
const topicQuery2 = detectTopic('Next.js caching strategies');
assert(topicQuery2 !== null, 'Detect topic-specific query 2');
assert(topicQuery2 && topicQuery2.isTopicSpecific === true, 'Query 2 is topic-specific');
if (topicQuery2) {
assertEqual(topicQuery2.topic, 'caching', 'Query 2 topic is "caching"');
assertEqual(topicQuery2.library, 'next.js', 'Query 2 library is "next.js"');
}
const topicQuery3 = detectTopic('Better Auth OAuth setup');
assert(topicQuery3 !== null, 'Detect topic-specific query 3');
assert(topicQuery3.isTopicSpecific === true, 'Query 3 is topic-specific');
const topicQuery4 = detectTopic('Using authentication with Better Auth');
assert(topicQuery4 !== null, 'Detect topic-specific query 4');
assert(topicQuery4.isTopicSpecific === true, 'Query 4 is topic-specific');
const topicQuery5 = detectTopic('Implement routing in Next.js');
assert(topicQuery5 !== null, 'Detect topic-specific query 5');
assert(topicQuery5.isTopicSpecific === true, 'Query 5 is topic-specific');
// Test general queries
console.log('\n## Testing general queries');
const generalQuery1 = detectTopic('Documentation for Next.js');
assert(generalQuery1 === null, 'Detect general query 1 (returns null)');
const generalQuery2 = detectTopic('Astro getting started');
assert(generalQuery2 === null, 'Detect general query 2 (returns null)');
const generalQuery3 = detectTopic('How to use Better Auth');
assert(generalQuery3 === null, 'Detect general query 3 (returns null)');
const generalQuery4 = detectTopic('Next.js API reference');
assert(generalQuery4 === null, 'Detect general query 4 (returns null)');
// Test edge cases
console.log('\n## Testing edge cases');
const edgeCase1 = detectTopic('');
assert(edgeCase1 === null, 'Empty string returns null');
const edgeCase2 = detectTopic(null);
assert(edgeCase2 === null, 'Null returns null');
const edgeCase3 = detectTopic('Random text without pattern');
assert(edgeCase3 === null, 'Non-matching query returns null');
// Summary
console.log('\n## Test Summary');
console.log(`Passed: ${passed}`);
console.log(`Failed: ${failed}`);
console.log(`Total: ${passed + failed}`);
process.exit(failed > 0 ? 1 : 0);

View File

@@ -0,0 +1,84 @@
#!/usr/bin/env node
/**
* Tests for fetch-docs.js
*/
const { buildContext7Url, getUrlVariations } = require('../fetch-docs');
// Test counter
let passed = 0;
let failed = 0;
function assert(condition, message) {
if (condition) {
console.log(`${message}`);
passed++;
} else {
console.error(`${message}`);
failed++;
}
}
function assertEqual(actual, expected, message) {
if (actual === expected) {
console.log(`${message}`);
passed++;
} else {
console.error(`${message}`);
console.error(` Expected: ${expected}`);
console.error(` Actual: ${actual}`);
failed++;
}
}
console.log('Running fetch-docs.js tests...\n');
// Test buildContext7Url
console.log('## Testing buildContext7Url()');
assertEqual(
buildContext7Url('vercel/next.js'),
'https://context7.com/vercel/next.js/llms.txt',
'Build URL for GitHub repo'
);
assertEqual(
buildContext7Url('vercel/next.js', 'cache'),
'https://context7.com/vercel/next.js/llms.txt?topic=cache',
'Build URL with topic parameter'
);
assertEqual(
buildContext7Url('shadcn-ui/ui', 'date'),
'https://context7.com/shadcn-ui/ui/llms.txt?topic=date',
'Build URL for shadcn with topic'
);
// Test getUrlVariations
console.log('\n## Testing getUrlVariations()');
async function testUrlVariations() {
const urls1 = await getUrlVariations('next.js', 'cache');
assert(urls1.length >= 2, 'Returns multiple URL variations with topic');
assert(urls1[0].includes('?topic=cache'), 'First URL has topic parameter');
assert(!urls1[1].includes('?topic='), 'Second URL has no topic parameter');
const urls2 = await getUrlVariations('shadcn/ui');
assert(urls2.length >= 1, 'Returns URL variations without topic');
assert(!urls2[0].includes('?topic='), 'URL has no topic parameter');
const urls3 = await getUrlVariations('astro', 'routing');
assert(urls3.length >= 2, 'Returns variations for known library');
assertEqual(urls3[0], 'https://context7.com/withastro/astro/llms.txt?topic=routing', 'Maps Astro correctly');
}
testUrlVariations().then(() => {
// Summary
console.log('\n## Test Summary');
console.log(`Passed: ${passed}`);
console.log(`Failed: ${failed}`);
console.log(`Total: ${passed + failed}`);
process.exit(failed > 0 ? 1 : 0);
});