W / test /gen-docs-models.test.js
Ac66's picture
Upload folder using huggingface_hub
2b64d42 verified
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { createHash } from 'node:crypto';
import { copyFileSync, mkdtempSync, readFileSync, rmSync, writeFileSync, mkdirSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
const ROOT = resolve(process.cwd());
function makeWorkspace({ includeHuggingFaceModel = false } = {}) {
const workspace = mkdtempSync(join(tmpdir(), 'wa-gen-docs-'));
const srcDir = join(workspace, 'src');
const docsDir = join(workspace, 'docs');
const scriptsDir = join(workspace, 'scripts');
const dashboardDir = join(srcDir, 'dashboard');
mkdirSync(srcDir, { recursive: true });
mkdirSync(docsDir, { recursive: true });
mkdirSync(scriptsDir, { recursive: true });
mkdirSync(dashboardDir, { recursive: true });
copyFileSync(join(ROOT, 'package.json'), join(workspace, 'package.json'));
copyFileSync(join(ROOT, 'src/models.js'), join(srcDir, 'models.js'));
copyFileSync(join(ROOT, 'scripts/gen-docs-models.js'), join(scriptsDir, 'gen-docs-models.js'));
copyFileSync(join(ROOT, 'docs/index.html'), join(docsDir, 'index.html'));
if (!includeHuggingFaceModel) {
return workspace;
}
const modelsPath = join(srcDir, 'models.js');
let source = readFileSync(modelsPath, 'utf8');
const marker = source.indexOf('// Build reverse lookup');
if (marker < 0) {
throw new Error('unexpected models.js structure: missing // Build reverse lookup marker');
}
const objectEndMatch = source.match(/\r?\n\};\r?\n\r?\n\/\/ Build reverse lookup/);
const objectEnd = objectEndMatch ? objectEndMatch.index : -1;
if (objectEnd < 0) {
throw new Error('unexpected models.js structure: missing end of MODELS object');
}
const patch = "\n 'model-huggingface-custom': { name: 'model-huggingface-custom', provider: 'huggingface', enumValue: 999999, modelUid: 'model-huggingface-custom', credit: 1 },\n";
source = `${source.slice(0, objectEnd + 1)}${patch}${source.slice(objectEnd + 1)}`;
writeFileSync(modelsPath, source, 'utf8');
return workspace;
}
function runGenerator(workspace) {
const result = spawnSync(process.execPath, ['scripts/gen-docs-models.js'], {
cwd: workspace,
encoding: 'utf8',
timeout: 20000,
});
return result;
}
function parseModels(htmlText) {
const start = htmlText.indexOf('const MODELS = [');
assert.ok(start >= 0, 'MODELS array anchor not found');
const open = htmlText.indexOf('[', start);
const close = htmlText.indexOf(' ];', start);
assert.ok(close > open, 'MODELS array end marker not found');
const literal = htmlText.slice(open, close + 3);
const models = new Function(`return ${literal}`)();
assert.ok(Array.isArray(models), 'MODELS should be an array');
return models;
}
function readDocsHtml(workspace) {
return readFileSync(join(workspace, 'docs', 'index.html'), 'utf8');
}
function sha256(content) {
return createHash('sha256').update(content).digest('hex');
}
describe('scripts/gen-docs-models.js', () => {
it('regenerates a parseable MODELS block and keeps HTML shape', () => {
const workspace = makeWorkspace();
try {
const result = runGenerator(workspace);
assert.equal(result.status, 0, `generator exit: ${result.status}, stderr=${result.stderr}`);
const html = readDocsHtml(workspace);
const models = parseModels(html);
assert.ok(html.includes('<html'), 'generated docs should include html root');
assert.ok(html.includes('</html>'), 'generated docs should include html close tag');
assert.equal(typeof html, 'string');
assert.ok(models.length >= 100, `expected at least 100 models, got ${models.length}`);
assert.ok(models.every(model => model?.k && model?.p && typeof model.c === 'number'));
// Pick a stable, non-deprecated marker. `adaptive` was removed from
// /v1/models in v2.0.51 (#109) — upstream rejects its UID — so it
// can't be used as a presence anchor. claude-sonnet-4.6 is the
// current default and is unlikely to be deprecated near-term.
assert.ok(models.some(model => model.k === 'claude-sonnet-4.6'));
} finally {
rmSync(workspace, { recursive: true, force: true });
}
});
it('is idempotent when run repeatedly on the same input', () => {
const workspace = makeWorkspace();
try {
const first = runGenerator(workspace);
assert.equal(first.status, 0, `first run failed: ${first.stderr}`);
const firstHtml = readDocsHtml(workspace);
const second = runGenerator(workspace);
assert.equal(second.status, 0, `second run failed: ${second.stderr}`);
const secondHtml = readDocsHtml(workspace);
assert.equal(sha256(firstHtml), sha256(secondHtml), 'generator output changed between runs');
assert.deepEqual(parseModels(firstHtml), parseModels(secondHtml));
} finally {
rmSync(workspace, { recursive: true, force: true });
}
});
it('supports unknown provider values when models are merged in', () => {
const workspace = makeWorkspace({ includeHuggingFaceModel: true });
try {
const result = runGenerator(workspace);
assert.equal(result.status, 0, `generator failed on unknown provider: ${result.stderr}`);
const html = readDocsHtml(workspace);
const models = parseModels(html);
assert.ok(models.some(model => model.k === 'model-huggingface-custom' && model.p === 'huggingface'));
} finally {
rmSync(workspace, { recursive: true, force: true });
}
});
});