fancive_obsidian-parallel-r.../tests/direct-settings.test.js
wujunchen 0264ef0b6c refactor: split direct-modules.test.js into 5 per-module test files
Replaces the monolithic direct-modules.test.js (780 lines) with focused
per-module test files sharing a common direct-test-setup.js. Each file
is under 165 lines. All existing test assertions preserved.

New files: direct-test-setup.js, direct-cache.test.js,
direct-providers.test.js, direct-settings.test.js, direct-i18n.test.js,
direct-streaming.test.js

Change-Id: Ie9cceaf3b9b71e618c0d7e524a5186b5c44079c8
2026-04-27 15:24:32 +08:00

103 lines
5.5 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); });