Skip to content

Commit 3e81456

Browse files
add semantic index regression tests
1 parent 1130e88 commit 3e81456

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import test from 'node:test';
2+
import assert from 'node:assert/strict';
3+
import fs from 'node:fs';
4+
import os from 'node:os';
5+
import path from 'node:path';
6+
import { buildInventory } from '../lib/inventory.mjs';
7+
import { compileContext } from '../lib/context.mjs';
8+
import { databaseStats, indexRepository } from '../lib/indexer.mjs';
9+
import { generate } from '../lib/pipeline.mjs';
10+
import { projectPaths, readJson, writeJson } from '../lib/core.mjs';
11+
12+
function fixture() {
13+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'docgen-v2-')); const p = projectPaths(root);
14+
fs.mkdirSync(path.join(root, 'src'), { recursive: true });
15+
fs.mkdirSync(path.dirname(p.config), { recursive: true });
16+
writeJson(p.project, { schemaVersion: '2.0', kitVersion: '2.0.0' });
17+
writeJson(p.config, { schemaVersion: '2.0', ignore: { binary: { enabled: true, maxTextFileBytes: 1024 * 1024 } }, context: { maxTokens: { default: 4000, generate: 4000 } }, execution: { generationBatchSize: 2 }, audit: { llmEnabled: false } });
18+
writeJson(p.state, { schemaVersion: '2.0', kitVersion: '2.0.0', stages: {}, pages: {} });
19+
return root;
20+
}
21+
22+
test('inventory excludes binary and docgenignore paths', () => {
23+
const root = fixture();
24+
fs.writeFileSync(path.join(root, 'src', 'Resource.java'), '@Path("/quotes")\nclass Resource { @GET void get() {} }\n');
25+
fs.writeFileSync(path.join(root, 'secret.txt'), 'ignore me');
26+
fs.writeFileSync(path.join(root, 'image.png'), Buffer.from([0x89,0x50,0x4e,0x47,0,1]));
27+
fs.writeFileSync(path.join(root, '.docgenignore'), 'secret.txt\n');
28+
const inv = buildInventory(root, { force: true });
29+
assert(inv.files.some((x) => x.path === 'src/Resource.java'));
30+
assert(!inv.files.some((x) => x.path === 'secret.txt'));
31+
assert(inv.excluded.some((x) => x.path === 'image.png'));
32+
});
33+
34+
test('index is incremental and extracts repository facts', () => {
35+
const root = fixture();
36+
fs.writeFileSync(path.join(root, 'src', 'Resource.java'), '@Path("/quotes")\nclass Resource { @POST void create() {} }\n');
37+
const first = indexRepository(root, { force: true });
38+
const second = indexRepository(root);
39+
const stats = databaseStats(root);
40+
assert.equal(first.changedFiles > 0, true);
41+
assert.equal(second.changedFiles, 0);
42+
assert.equal(second.unchangedFiles > 0, true);
43+
assert.equal(stats.facts > 0, true);
44+
});
45+
46+
test('context compiler stays within configured budget', () => {
47+
const root = fixture();
48+
for (let i = 0; i < 60; i++) fs.writeFileSync(path.join(root, 'src', `Resource${i}.java`), `@Path("/items/${i}")\nclass Resource${i} { @GET void get${i}() {} }\n`);
49+
indexRepository(root, { force: true });
50+
const { payload } = compileContext(root, { stage: 'generate', target: 'api', query: 'endpoint path resource', maxTokens: 1200 });
51+
assert(payload.estimatedTokens <= 1200);
52+
assert(payload.facts.length > 0);
53+
assert(payload.omissions.facts > 0);
54+
});
55+
56+
test('reference catalog page is rendered without a provider call', async () => {
57+
const root = fixture(); const p = projectPaths(root);
58+
fs.writeFileSync(path.join(root, 'src', 'Resource.java'), '@Path("/quotes")\nclass Resource { @POST void create() {} }\n');
59+
indexRepository(root, { force: true });
60+
fs.mkdirSync(p.model, { recursive: true });
61+
writeJson(path.join(p.model, 'catalogs.json'), { schemaVersion: '2.0', endpoints: [{ id: 'create-quote', name: 'Create quote', method: 'POST', path: '/quotes', evidence: [{ path: 'src/Resource.java', startLine: 1 }] }], messageHandlers: [], externalDependencies: [], dataStores: [], scheduledJobs: [] });
62+
writeJson(p.plan, { schemaVersion: '2.0', pages: [{ id: 'endpoint-catalog', title: 'Endpoint Catalog', summary: 'HTTP API reference.', category: 'api', mode: 'reference', type: 'reference', order: 1, audience: ['engineer'], coverageTags: ['endpoint-catalog'], query: 'endpoints', requiredSections: [], relatedPages: [] }] });
63+
const result = await generate(root);
64+
assert.equal(result.providerPages, 0);
65+
const output = fs.readFileSync(path.join(root, 'docs', 'api', 'endpoint-catalog.md'), 'utf8');
66+
assert.match(output, /POST/);
67+
assert.match(output, /\/quotes/);
68+
assert.equal(fs.existsSync(path.join(p.telemetry, 'provider-runs.jsonl')), false);
69+
});

0 commit comments

Comments
 (0)