mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-26 00:55:16 -07:00
47f92129af
- Move computeWordClass tests from subtitle-render.test.ts to subtitle-render-word-class.test.ts - Extract createToken helper into subtitle-render-test-helpers.ts for reuse - Register new test file in test:core:src and test:core:dist scripts
207 lines
5.3 KiB
TypeScript
207 lines
5.3 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import type { MergedToken } from '../types';
|
|
import { computeWordClass } from './subtitle-render.js';
|
|
import { createToken } from './subtitle-render-test-helpers.js';
|
|
|
|
test('computeWordClass preserves known and n+1 classes while adding JLPT classes', () => {
|
|
const knownJlpt = createToken({
|
|
isKnown: true,
|
|
jlptLevel: 'N1',
|
|
surface: '猫',
|
|
});
|
|
const nPlusOneJlpt = createToken({
|
|
isNPlusOneTarget: true,
|
|
jlptLevel: 'N2',
|
|
surface: '犬',
|
|
});
|
|
|
|
assert.equal(computeWordClass(knownJlpt), 'word word-known word-jlpt-n1');
|
|
assert.equal(computeWordClass(nPlusOneJlpt), 'word word-n-plus-one word-jlpt-n2');
|
|
});
|
|
|
|
test('computeWordClass applies name-match class ahead of known, n+1, frequency, and JLPT classes when enabled', () => {
|
|
const token = createToken({
|
|
isKnown: true,
|
|
isNPlusOneTarget: true,
|
|
jlptLevel: 'N2',
|
|
frequencyRank: 10,
|
|
surface: 'アクア',
|
|
}) as MergedToken & { isNameMatch?: boolean };
|
|
token.isNameMatch = true;
|
|
|
|
assert.equal(
|
|
computeWordClass(token, {
|
|
nameMatchEnabled: true,
|
|
enabled: true,
|
|
topX: 100,
|
|
mode: 'single',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#000000', '#000000', '#000000', '#000000', '#000000'] as const,
|
|
}),
|
|
'word word-name-match',
|
|
);
|
|
});
|
|
|
|
test('computeWordClass skips name-match class by default', () => {
|
|
const token = createToken({
|
|
surface: 'アクア',
|
|
}) as MergedToken & { isNameMatch?: boolean };
|
|
token.isNameMatch = true;
|
|
|
|
assert.equal(computeWordClass(token), 'word');
|
|
});
|
|
|
|
test('computeWordClass skips name-match class when disabled', () => {
|
|
const token = createToken({
|
|
surface: 'アクア',
|
|
}) as MergedToken & { isNameMatch?: boolean };
|
|
token.isNameMatch = true;
|
|
|
|
assert.equal(
|
|
computeWordClass(token, {
|
|
nameMatchEnabled: false,
|
|
enabled: true,
|
|
topX: 100,
|
|
mode: 'single',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#000000', '#000000', '#000000', '#000000', '#000000'] as const,
|
|
}),
|
|
'word',
|
|
);
|
|
});
|
|
|
|
test('computeWordClass keeps known and N+1 color classes exclusive over frequency classes', () => {
|
|
const known = createToken({
|
|
isKnown: true,
|
|
frequencyRank: 10,
|
|
surface: '既知',
|
|
});
|
|
const nPlusOne = createToken({
|
|
isNPlusOneTarget: true,
|
|
frequencyRank: 10,
|
|
surface: '目標',
|
|
});
|
|
const frequency = createToken({
|
|
frequencyRank: 10,
|
|
surface: '頻度',
|
|
});
|
|
|
|
assert.equal(
|
|
computeWordClass(known, {
|
|
enabled: true,
|
|
topX: 100,
|
|
mode: 'single',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#000000', '#000000', '#000000', '#000000', '#000000'] as const,
|
|
}),
|
|
'word word-known',
|
|
);
|
|
assert.equal(
|
|
computeWordClass(nPlusOne, {
|
|
enabled: true,
|
|
topX: 100,
|
|
mode: 'single',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#000000', '#000000', '#000000', '#000000', '#000000'] as const,
|
|
}),
|
|
'word word-n-plus-one',
|
|
);
|
|
assert.equal(
|
|
computeWordClass(frequency, {
|
|
enabled: true,
|
|
topX: 100,
|
|
mode: 'single',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#000000', '#000000', '#000000', '#000000', '#000000'] as const,
|
|
}),
|
|
'word word-frequency-single',
|
|
);
|
|
});
|
|
|
|
test('computeWordClass adds frequency class for single mode when rank is within topX', () => {
|
|
const token = createToken({
|
|
surface: '猫',
|
|
frequencyRank: 50,
|
|
});
|
|
|
|
const actual = computeWordClass(token, {
|
|
enabled: true,
|
|
topX: 100,
|
|
mode: 'single',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#000000', '#000000', '#000000', '#000000', '#000000'] as const,
|
|
});
|
|
|
|
assert.equal(actual, 'word word-frequency-single');
|
|
});
|
|
|
|
test('computeWordClass adds frequency class when rank equals topX', () => {
|
|
const token = createToken({
|
|
surface: '水',
|
|
frequencyRank: 100,
|
|
});
|
|
|
|
const actual = computeWordClass(token, {
|
|
enabled: true,
|
|
topX: 100,
|
|
mode: 'single',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#000000', '#000000', '#000000', '#000000', '#000000'] as const,
|
|
});
|
|
|
|
assert.equal(actual, 'word word-frequency-single');
|
|
});
|
|
|
|
test('computeWordClass adds frequency class for banded mode', () => {
|
|
const token = createToken({
|
|
surface: '犬',
|
|
frequencyRank: 250,
|
|
});
|
|
|
|
const actual = computeWordClass(token, {
|
|
enabled: true,
|
|
topX: 1000,
|
|
mode: 'banded',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#111111', '#222222', '#333333', '#444444', '#555555'] as const,
|
|
});
|
|
|
|
assert.equal(actual, 'word word-frequency-band-2');
|
|
});
|
|
|
|
test('computeWordClass uses configured band count for banded mode', () => {
|
|
const token = createToken({
|
|
surface: '犬',
|
|
frequencyRank: 2,
|
|
});
|
|
|
|
const actual = computeWordClass(token, {
|
|
enabled: true,
|
|
topX: 4,
|
|
mode: 'banded',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#111111', '#222222', '#333333', '#444444', '#555555'],
|
|
} as any);
|
|
|
|
assert.equal(actual, 'word word-frequency-band-3');
|
|
});
|
|
|
|
test('computeWordClass skips frequency class when rank is out of topX', () => {
|
|
const token = createToken({
|
|
surface: '犬',
|
|
frequencyRank: 1200,
|
|
});
|
|
|
|
const actual = computeWordClass(token, {
|
|
enabled: true,
|
|
topX: 1000,
|
|
mode: 'single',
|
|
singleColor: '#000000',
|
|
bandedColors: ['#000000', '#000000', '#000000', '#000000', '#000000'] as const,
|
|
});
|
|
|
|
assert.equal(actual, 'word');
|
|
});
|