fancive_obsidian-parallel-r.../tests/direct-settings.test.js
wujunchen 0bf5ab12b1 lint: extend Biome coverage to tests/ and scripts/
Add tests/**/*.js and scripts/**/*.mjs to biome.json includes and
update npm lint scripts to cover these directories. Auto-fixed all
formatting issues in 26 files.

Change-Id: I8c2763cb9683616a8abc1484d91bf8af79bb590e
2026-04-27 19:53:35 +08:00

119 lines
5.6 KiB
JavaScript

const { assert, requireBundledModule, cleanup } = require('./direct-test-setup');
(async () => {
try {
const settings = await requireBundledModule('src/settings.ts');
const cards = await requireBundledModule('src/cards.ts');
const vault = await requireBundledModule('src/vault.ts');
// ── settings.ts ──
assert.notStrictEqual(
settings.generationFingerprint({ ...settings.DEFAULT_SETTINGS, model: 'a' }),
settings.generationFingerprint({ ...settings.DEFAULT_SETTINGS, model: 'b' }),
);
// applyApiProviderPreset: model swap
const anthropicSettings = { ...settings.DEFAULT_SETTINGS, apiProvider: 'anthropic', model: 'claude-sonnet-4-6' };
const switchedToOpenAi = settings.applyApiProviderPreset(anthropicSettings, 'openai');
assert.strictEqual(switchedToOpenAi.apiProvider, 'openai');
assert.strictEqual(switchedToOpenAi.apiFormat, 'openai-chat');
assert.strictEqual(switchedToOpenAi.model, 'gpt-5.1');
const customModelSettings = { ...settings.DEFAULT_SETTINGS, apiProvider: 'anthropic', model: 'my-custom-model' };
assert.strictEqual(settings.applyApiProviderPreset(customModelSettings, 'openai').model, 'my-custom-model');
const openaiWithPresetModel = { ...settings.DEFAULT_SETTINGS, apiProvider: 'openai', model: 'gpt-5.1' };
const switchedToGoogle = settings.applyApiProviderPreset(openaiWithPresetModel, 'google');
assert.strictEqual(switchedToGoogle.model, 'gemini-3-pro-preview');
const emptyModelSettings = { ...settings.DEFAULT_SETTINGS, apiProvider: 'anthropic', model: '' };
assert.strictEqual(settings.applyApiProviderPreset(emptyModelSettings, 'deepseek').model, 'deepseek-chat');
assert.strictEqual(anthropicSettings.model, 'claude-sonnet-4-6', 'does not mutate input');
// normalizeCardCount
assert.strictEqual(settings.normalizeCardCount(5, 10), 5);
assert.strictEqual(settings.normalizeCardCount(0, 10), 1);
assert.strictEqual(settings.normalizeCardCount(-5, 10), 1);
assert.strictEqual(settings.normalizeCardCount(100, 10), 30);
assert.strictEqual(settings.normalizeCardCount(NaN, 7), 7);
assert.strictEqual(settings.normalizeCardCount(undefined, 7), 7);
assert.strictEqual(settings.normalizeCardCount('15', 7), 15);
// getApiKey
assert.strictEqual(settings.getApiKey({ ...settings.DEFAULT_SETTINGS, apiKey: 'direct-key' }), 'direct-key');
assert.strictEqual(settings.getApiKey({ ...settings.DEFAULT_SETTINGS, apiKey: '', apiKeyEnvVar: '' }), '');
assert.strictEqual(settings.getApiKey({ ...settings.DEFAULT_SETTINGS, apiKey: ' trimmed ' }), 'trimmed');
const envVarName = '__PARALLEL_READER_TEST_KEY__';
process.env[envVarName] = 'env-key-val';
try {
assert.strictEqual(
settings.getApiKey({ ...settings.DEFAULT_SETTINGS, apiKey: '', apiKeyEnvVar: envVarName }),
'env-key-val',
);
assert.strictEqual(
settings.getApiKey({ ...settings.DEFAULT_SETTINGS, apiKey: 'direct', apiKeyEnvVar: envVarName }),
'direct',
);
} finally {
delete process.env[envVarName];
}
// cacheEntryMatches
const testContent = 'hello world';
const testSettings = { ...settings.DEFAULT_SETTINGS };
const validEntry = {
schemaVersion: settings.CACHE_SCHEMA_VERSION,
contentHash: settings.hashContent(testContent),
settingsHash: settings.generationFingerprint(testSettings),
cards: [],
generatedAt: '2024-01-01T00:00:00.000Z',
};
assert.strictEqual(settings.cacheEntryMatches(validEntry, testContent, testSettings), true);
assert.strictEqual(settings.cacheEntryMatches(null, testContent, testSettings), false);
assert.strictEqual(
settings.cacheEntryMatches({ ...validEntry, contentHash: 'wrong' }, testContent, testSettings),
false,
);
assert.strictEqual(
settings.cacheEntryMatches({ ...validEntry, schemaVersion: 999 }, testContent, testSettings),
false,
);
assert.strictEqual(settings.cacheEntryMatches(validEntry, 'different content', testSettings), false);
// ── cards.ts: resolveCardAnchors ──
const content = 'line0 hello\nline1 world\nline2 anchor here\nline3 end';
const rawCards = [
{ title: 'A', anchor: 'anchor here', gist: 'gA', bullets: ['b1'] },
{ title: 'B', anchor: 'hello', gist: 'gB', bullets: [] },
{ title: 'C', anchor: 'not_found', gist: 'gC', bullets: [] },
];
const resolved = cards.resolveCardAnchors(content, rawCards);
assert.strictEqual(resolved[0].title, 'B');
assert.strictEqual(resolved[0].startLine, 0);
assert.strictEqual(resolved[1].title, 'A');
assert.strictEqual(resolved[1].startLine, 2);
assert.strictEqual(resolved[2].title, 'C');
assert.ok(resolved[2].startLine < 0);
assert.deepStrictEqual(cards.resolveCardAnchors('', []), []);
assert.deepStrictEqual(cards.resolveCardAnchors('content', null), []);
assert.deepStrictEqual(cards.resolveCardAnchors('content', undefined), []);
assert.strictEqual(resolved[0].level, 2, 'level defaults to 2');
// ── vault.ts ──
assert.strictEqual(vault.normalizeVaultPath('Reading/Articles'), 'Reading/Articles');
assert.strictEqual(vault.normalizeVaultPath(' Reading / Articles '), 'Reading/Articles');
assert.strictEqual(vault.normalizeVaultPath('../bad/../path'), 'bad/path');
assert.strictEqual(vault.normalizeVaultPath(''), '');
assert.strictEqual(vault.normalizeVaultPath(null), '');
assert.strictEqual(vault.normalizeVaultPath('a//b///c'), 'a/b/c');
console.log('direct settings tests passed');
} finally {
cleanup();
}
})().catch((e) => {
console.error(e);
process.exit(1);
});