mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-06-10 03:13:32 -07:00
361c0f1334
- Default notificationType fallback changed from 'overlay' to 'osd' - isVisibleOverlayContentReady guards on overlay visible + window ready - All overlay hide paths dismiss loading OSD notification - notifyConfiguredStatus falls back to desktop when overlay not ready - anilist deps builder preserves undefined optional callbacks as undefined - settingsEnumValues field added to ConfigOptionRegistryEntry - Drop !important from z-index; lower yomitan popup z-index below notification stack
285 lines
9.4 KiB
TypeScript
285 lines
9.4 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import {
|
|
createStartupOsdSequencer,
|
|
type StartupOsdSequencerCharacterDictionaryEvent,
|
|
} from './startup-osd-sequencer';
|
|
|
|
function makeDictionaryEvent(
|
|
phase: StartupOsdSequencerCharacterDictionaryEvent['phase'],
|
|
message: string,
|
|
): StartupOsdSequencerCharacterDictionaryEvent {
|
|
return {
|
|
phase,
|
|
message,
|
|
};
|
|
}
|
|
|
|
test('startup OSD keeps dictionary progress hidden until tokenization and annotation loading finish', () => {
|
|
const osdMessages: string[] = [];
|
|
const sequencer = createStartupOsdSequencer({
|
|
showOsd: (message) => {
|
|
osdMessages.push(message);
|
|
},
|
|
});
|
|
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('syncing', 'Updating character dictionary for Frieren...'),
|
|
);
|
|
sequencer.showAnnotationLoading('Loading subtitle annotations |');
|
|
sequencer.markTokenizationReady();
|
|
|
|
assert.deepEqual(osdMessages, ['Loading subtitle annotations |']);
|
|
|
|
sequencer.showAnnotationLoading('Loading subtitle annotations /');
|
|
assert.deepEqual(osdMessages, [
|
|
'Loading subtitle annotations |',
|
|
'Loading subtitle annotations /',
|
|
]);
|
|
|
|
sequencer.markAnnotationLoadingComplete('Subtitle annotations loaded');
|
|
assert.deepEqual(osdMessages, [
|
|
'Loading subtitle annotations |',
|
|
'Loading subtitle annotations /',
|
|
'Updating character dictionary for Frieren...',
|
|
]);
|
|
});
|
|
|
|
test('startup OSD buffers checking behind annotations and replaces it with later generating progress', () => {
|
|
const osdMessages: string[] = [];
|
|
const sequencer = createStartupOsdSequencer({
|
|
showOsd: (message) => {
|
|
osdMessages.push(message);
|
|
},
|
|
});
|
|
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('checking', 'Checking character dictionary for Frieren...'),
|
|
);
|
|
sequencer.showAnnotationLoading('Loading subtitle annotations |');
|
|
sequencer.markTokenizationReady();
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('generating', 'Generating character dictionary for Frieren...'),
|
|
);
|
|
|
|
assert.deepEqual(osdMessages, [
|
|
'Loading subtitle annotations |',
|
|
'Generating character dictionary for Frieren...',
|
|
]);
|
|
|
|
sequencer.markAnnotationLoadingComplete('Subtitle annotations loaded');
|
|
|
|
assert.deepEqual(osdMessages, [
|
|
'Loading subtitle annotations |',
|
|
'Generating character dictionary for Frieren...',
|
|
]);
|
|
});
|
|
|
|
test('startup OSD replaces earlier dictionary progress with later building progress', () => {
|
|
const osdMessages: string[] = [];
|
|
const sequencer = createStartupOsdSequencer({
|
|
showOsd: (message) => {
|
|
osdMessages.push(message);
|
|
},
|
|
});
|
|
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('syncing', 'Updating character dictionary for Frieren...'),
|
|
);
|
|
sequencer.showAnnotationLoading('Loading subtitle annotations |');
|
|
sequencer.markTokenizationReady();
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('building', 'Building character dictionary for Frieren...'),
|
|
);
|
|
|
|
sequencer.markAnnotationLoadingComplete('Subtitle annotations loaded');
|
|
|
|
assert.deepEqual(osdMessages, [
|
|
'Loading subtitle annotations |',
|
|
'Building character dictionary for Frieren...',
|
|
]);
|
|
});
|
|
|
|
test('startup OSD shows dictionary ready when progress completed before it became visible', () => {
|
|
const osdMessages: string[] = [];
|
|
const sequencer = createStartupOsdSequencer({
|
|
showOsd: (message) => {
|
|
osdMessages.push(message);
|
|
},
|
|
});
|
|
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('syncing', 'Updating character dictionary for Frieren...'),
|
|
);
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('ready', 'Character dictionary ready for Frieren'),
|
|
);
|
|
sequencer.markTokenizationReady();
|
|
sequencer.markAnnotationLoadingComplete('Subtitle annotations loaded');
|
|
|
|
assert.deepEqual(osdMessages, [
|
|
'Character dictionary ready for Frieren',
|
|
'Subtitle annotations loaded',
|
|
]);
|
|
});
|
|
|
|
test('startup OSD shows dictionary failure after annotation loading completes', () => {
|
|
const osdMessages: string[] = [];
|
|
const sequencer = createStartupOsdSequencer({
|
|
showOsd: (message) => {
|
|
osdMessages.push(message);
|
|
},
|
|
});
|
|
|
|
sequencer.showAnnotationLoading('Loading subtitle annotations |');
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('failed', 'Character dictionary sync failed for Frieren: boom'),
|
|
);
|
|
sequencer.markTokenizationReady();
|
|
sequencer.markAnnotationLoadingComplete('Subtitle annotations loaded');
|
|
|
|
assert.deepEqual(osdMessages, [
|
|
'Loading subtitle annotations |',
|
|
'Character dictionary sync failed for Frieren: boom',
|
|
]);
|
|
});
|
|
|
|
test('startup OSD reset keeps tokenization ready after first warmup', () => {
|
|
const osdMessages: string[] = [];
|
|
const sequencer = createStartupOsdSequencer({
|
|
showOsd: (message) => {
|
|
osdMessages.push(message);
|
|
},
|
|
});
|
|
|
|
sequencer.markTokenizationReady();
|
|
sequencer.reset();
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('syncing', 'Updating character dictionary for Frieren...'),
|
|
);
|
|
|
|
assert.deepEqual(osdMessages, ['Updating character dictionary for Frieren...']);
|
|
});
|
|
|
|
test('startup OSD reset preserves in-flight tokenization loading for ready update', () => {
|
|
const calls: string[] = [];
|
|
const sequencer = createStartupOsdSequencer({
|
|
getNotificationType: () => 'both',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showOverlayNotification: (payload) => {
|
|
calls.push(
|
|
`overlay:${payload.id}:${payload.title}:${payload.body}:${payload.variant}:${payload.persistent ? 'pin' : 'auto'}`,
|
|
);
|
|
},
|
|
showDesktopNotification: (title, options) => {
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`);
|
|
},
|
|
});
|
|
|
|
sequencer.showTokenizationLoading('Loading subtitle tokenization...');
|
|
sequencer.reset();
|
|
sequencer.markTokenizationReady();
|
|
|
|
assert.deepEqual(calls, [
|
|
'overlay:startup-tokenization:Subtitle tokenization:Loading subtitle tokenization...:progress:pin',
|
|
'overlay:startup-tokenization:Subtitle tokenization:Subtitle tokenization ready:success:auto',
|
|
'desktop:SubMiner:Subtitle tokenization ready',
|
|
]);
|
|
});
|
|
|
|
test('startup OSD shows later dictionary progress immediately once tokenization is ready', () => {
|
|
const osdMessages: string[] = [];
|
|
const sequencer = createStartupOsdSequencer({
|
|
showOsd: (message) => {
|
|
osdMessages.push(message);
|
|
},
|
|
});
|
|
|
|
sequencer.showAnnotationLoading('Loading subtitle annotations |');
|
|
sequencer.markTokenizationReady();
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('generating', 'Generating character dictionary for Frieren...'),
|
|
);
|
|
|
|
assert.deepEqual(osdMessages, [
|
|
'Loading subtitle annotations |',
|
|
'Generating character dictionary for Frieren...',
|
|
]);
|
|
|
|
sequencer.markAnnotationLoadingComplete('Subtitle annotations loaded');
|
|
|
|
assert.deepEqual(osdMessages, [
|
|
'Loading subtitle annotations |',
|
|
'Generating character dictionary for Frieren...',
|
|
]);
|
|
});
|
|
|
|
test('startup OSD keeps dictionary progress pending when mpv osd is unavailable', () => {
|
|
const osdMessages: string[] = [];
|
|
let osdAvailable = false;
|
|
const sequencer = createStartupOsdSequencer({
|
|
showOsd: (message) => {
|
|
osdMessages.push(message);
|
|
return osdAvailable;
|
|
},
|
|
});
|
|
|
|
sequencer.markTokenizationReady();
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('generating', 'Generating character dictionary for Frieren...'),
|
|
);
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('ready', 'Character dictionary ready for Frieren'),
|
|
);
|
|
|
|
assert.deepEqual(osdMessages, [
|
|
'Generating character dictionary for Frieren...',
|
|
'Character dictionary ready for Frieren',
|
|
]);
|
|
|
|
osdAvailable = true;
|
|
sequencer.notifyCharacterDictionaryStatus(
|
|
makeDictionaryEvent('ready', 'Character dictionary ready for Frieren'),
|
|
);
|
|
|
|
assert.deepEqual(osdMessages, [
|
|
'Generating character dictionary for Frieren...',
|
|
'Character dictionary ready for Frieren',
|
|
'Character dictionary ready for Frieren',
|
|
]);
|
|
});
|
|
|
|
test('startup notifications route tokenization and annotation status to overlay and system without osd for both', () => {
|
|
const calls: string[] = [];
|
|
const sequencer = createStartupOsdSequencer({
|
|
getNotificationType: () => 'both',
|
|
showOsd: (message) => {
|
|
calls.push(`osd:${message}`);
|
|
},
|
|
showOverlayNotification: (payload) => {
|
|
calls.push(
|
|
`overlay:${payload.id}:${payload.title}:${payload.body}:${payload.variant}:${payload.persistent ? 'pin' : 'auto'}`,
|
|
);
|
|
},
|
|
showDesktopNotification: (title, options) => {
|
|
calls.push(`desktop:${title}:${options.body ?? ''}`);
|
|
},
|
|
});
|
|
|
|
sequencer.showTokenizationLoading('Loading subtitle tokenization...');
|
|
sequencer.markTokenizationReady();
|
|
sequencer.showAnnotationLoading('Loading subtitle annotations |');
|
|
sequencer.markAnnotationLoadingComplete('Subtitle annotations loaded');
|
|
|
|
assert.deepEqual(calls, [
|
|
'overlay:startup-tokenization:Subtitle tokenization:Loading subtitle tokenization...:progress:pin',
|
|
'overlay:startup-tokenization:Subtitle tokenization:Subtitle tokenization ready:success:auto',
|
|
'desktop:SubMiner:Subtitle tokenization ready',
|
|
'overlay:startup-subtitle-annotations:Subtitle annotations:Loading subtitle annotations |:progress:pin',
|
|
'overlay:startup-subtitle-annotations:Subtitle annotations:Subtitle annotations loaded:success:auto',
|
|
'desktop:SubMiner:Subtitle annotations loaded',
|
|
]);
|
|
});
|