mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-07-30 07:21:32 -07:00
refactor: split anki-connect and stats-server resolvers into modules (#169)
This commit is contained in:
@@ -3,6 +3,7 @@ import test from 'node:test';
|
||||
import { DEFAULT_CONFIG, deepCloneConfig } from '../definitions';
|
||||
import { createWarningCollector } from '../warnings';
|
||||
import { applyAnkiConnectResolution } from './anki-connect';
|
||||
import { applyAnkiKnownWordsResolution } from './anki-connect/known-words';
|
||||
import type { ResolveContext } from './context';
|
||||
|
||||
function makeContext(ankiConnect: unknown): {
|
||||
@@ -39,6 +40,90 @@ test('modern invalid knownWords.highlightEnabled warns modern key and does not f
|
||||
);
|
||||
});
|
||||
|
||||
test('invalid modern known-words primitive values warn and keep defaults', () => {
|
||||
const { context, warnings } = makeContext({
|
||||
knownWords: {
|
||||
refreshMinutes: 'daily',
|
||||
matchMode: false,
|
||||
},
|
||||
nPlusOne: {
|
||||
minSentenceWords: 'three',
|
||||
},
|
||||
});
|
||||
|
||||
applyAnkiConnectResolution(context);
|
||||
|
||||
assert.equal(
|
||||
context.resolved.ankiConnect.knownWords.refreshMinutes,
|
||||
DEFAULT_CONFIG.ankiConnect.knownWords.refreshMinutes,
|
||||
);
|
||||
assert.equal(
|
||||
context.resolved.ankiConnect.knownWords.matchMode,
|
||||
DEFAULT_CONFIG.ankiConnect.knownWords.matchMode,
|
||||
);
|
||||
assert.equal(
|
||||
context.resolved.ankiConnect.nPlusOne.minSentenceWords,
|
||||
DEFAULT_CONFIG.ankiConnect.nPlusOne.minSentenceWords,
|
||||
);
|
||||
assert.deepEqual(
|
||||
warnings.map((warning) => warning.path),
|
||||
[
|
||||
'ankiConnect.knownWords.refreshMinutes',
|
||||
'ankiConnect.nPlusOne.minSentenceWords',
|
||||
'ankiConnect.knownWords.matchMode',
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
test('invalid legacy known-words primitive values warn and keep defaults', () => {
|
||||
const { context, warnings } = makeContext({
|
||||
behavior: {
|
||||
nPlusOneHighlightEnabled: 'yes',
|
||||
nPlusOneRefreshMinutes: 'daily',
|
||||
nPlusOneMatchMode: false,
|
||||
},
|
||||
});
|
||||
|
||||
applyAnkiConnectResolution(context);
|
||||
|
||||
assert.equal(
|
||||
context.resolved.ankiConnect.knownWords.highlightEnabled,
|
||||
DEFAULT_CONFIG.ankiConnect.knownWords.highlightEnabled,
|
||||
);
|
||||
assert.equal(
|
||||
context.resolved.ankiConnect.knownWords.refreshMinutes,
|
||||
DEFAULT_CONFIG.ankiConnect.knownWords.refreshMinutes,
|
||||
);
|
||||
assert.equal(
|
||||
context.resolved.ankiConnect.knownWords.matchMode,
|
||||
DEFAULT_CONFIG.ankiConnect.knownWords.matchMode,
|
||||
);
|
||||
assert.deepEqual(
|
||||
warnings.map((warning) => warning.path),
|
||||
[
|
||||
'ankiConnect.behavior.nPlusOneHighlightEnabled',
|
||||
'ankiConnect.behavior.nPlusOneRefreshMinutes',
|
||||
'ankiConnect.behavior.nPlusOneMatchMode',
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
test('known-words resolution can run independently from other Anki domains', () => {
|
||||
const { context, warnings } = makeContext({
|
||||
knownWords: { highlightEnabled: true },
|
||||
proxy: { port: -1 },
|
||||
});
|
||||
const ankiConnect = context.src.ankiConnect as Record<string, unknown>;
|
||||
|
||||
applyAnkiKnownWordsResolution(context, ankiConnect, {});
|
||||
|
||||
assert.equal(context.resolved.ankiConnect.knownWords.highlightEnabled, true);
|
||||
assert.equal(
|
||||
warnings.some((warning) => warning.path.startsWith('ankiConnect.proxy')),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test('normalizes ankiConnect tags by trimming and deduping', () => {
|
||||
const { context, warnings } = makeContext({
|
||||
tags: [' SubMiner ', 'Mining', 'SubMiner', ' Mining '],
|
||||
@@ -177,6 +262,40 @@ test('accepts ankiConnect.media.syncAnimatedImageToWordAudio override', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('invalid modern Anki subtrees warn and keep resolved defaults', () => {
|
||||
const { context, warnings } = makeContext({
|
||||
fields: { word: 7 },
|
||||
media: { generateAudio: 'yes' },
|
||||
behavior: { overwriteAudio: 'yes' },
|
||||
metadata: { pattern: false },
|
||||
});
|
||||
|
||||
applyAnkiConnectResolution(context);
|
||||
|
||||
assert.equal(context.resolved.ankiConnect.fields.word, DEFAULT_CONFIG.ankiConnect.fields.word);
|
||||
assert.equal(
|
||||
context.resolved.ankiConnect.media.generateAudio,
|
||||
DEFAULT_CONFIG.ankiConnect.media.generateAudio,
|
||||
);
|
||||
assert.equal(
|
||||
context.resolved.ankiConnect.behavior.overwriteAudio,
|
||||
DEFAULT_CONFIG.ankiConnect.behavior.overwriteAudio,
|
||||
);
|
||||
assert.equal(
|
||||
context.resolved.ankiConnect.metadata.pattern,
|
||||
DEFAULT_CONFIG.ankiConnect.metadata.pattern,
|
||||
);
|
||||
assert.deepEqual(
|
||||
warnings.map((warning) => warning.path),
|
||||
[
|
||||
'ankiConnect.fields.word',
|
||||
'ankiConnect.media.generateAudio',
|
||||
'ankiConnect.behavior.overwriteAudio',
|
||||
'ankiConnect.metadata.pattern',
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
test('maps legacy ankiConnect.wordField to modern ankiConnect.fields.word', () => {
|
||||
const { context, warnings } = makeContext({
|
||||
wordField: 'TargetWordLegacy',
|
||||
|
||||
Reference in New Issue
Block a user