mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-25 00:11:26 -07:00
167 lines
5.2 KiB
TypeScript
167 lines
5.2 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import {
|
|
createGetAnilistMediaGuessRuntimeStateHandler,
|
|
createGetCurrentAnilistMediaKeyHandler,
|
|
createResetAnilistMediaGuessStateHandler,
|
|
createResetAnilistMediaTrackingHandler,
|
|
createSetAnilistMediaGuessRuntimeStateHandler,
|
|
} from './anilist-media-state';
|
|
|
|
test('get current anilist media key trims and normalizes empty path', () => {
|
|
const getKey = createGetCurrentAnilistMediaKeyHandler({
|
|
getCurrentMediaPath: () => ' /tmp/video.mkv ',
|
|
});
|
|
const getEmptyKey = createGetCurrentAnilistMediaKeyHandler({
|
|
getCurrentMediaPath: () => ' ',
|
|
});
|
|
|
|
assert.equal(getKey(), '/tmp/video.mkv');
|
|
assert.equal(getEmptyKey(), null);
|
|
});
|
|
|
|
test('reset anilist media tracking clears duration/guess/probe state', () => {
|
|
let mediaKey: string | null = 'old';
|
|
let mediaDurationSec: number | null = 123;
|
|
let mediaGuess: { title: string } | null = { title: 'guess' };
|
|
let mediaGuessPromise: Promise<unknown> | null = Promise.resolve(null);
|
|
let lastDurationProbeAtMs = 999;
|
|
|
|
const reset = createResetAnilistMediaTrackingHandler({
|
|
setMediaKey: (value) => {
|
|
mediaKey = value;
|
|
},
|
|
setMediaDurationSec: (value) => {
|
|
mediaDurationSec = value;
|
|
},
|
|
setMediaGuess: (value) => {
|
|
mediaGuess = value as { title: string } | null;
|
|
},
|
|
setMediaGuessPromise: (value) => {
|
|
mediaGuessPromise = value;
|
|
},
|
|
setLastDurationProbeAtMs: (value) => {
|
|
lastDurationProbeAtMs = value;
|
|
},
|
|
});
|
|
|
|
reset('/new/media');
|
|
assert.equal(mediaKey, '/new/media');
|
|
assert.equal(mediaDurationSec, null);
|
|
assert.equal(mediaGuess, null);
|
|
assert.equal(mediaGuessPromise, null);
|
|
assert.equal(lastDurationProbeAtMs, 0);
|
|
});
|
|
|
|
test('reset anilist media tracking is idempotent', () => {
|
|
const state = {
|
|
mediaKey: 'old' as string | null,
|
|
mediaDurationSec: 123 as number | null,
|
|
mediaGuess: { title: 'guess' } as { title: string } | null,
|
|
mediaGuessPromise: Promise.resolve(null) as Promise<unknown> | null,
|
|
lastDurationProbeAtMs: 999,
|
|
};
|
|
|
|
const reset = createResetAnilistMediaTrackingHandler({
|
|
setMediaKey: (value) => {
|
|
state.mediaKey = value;
|
|
},
|
|
setMediaDurationSec: (value) => {
|
|
state.mediaDurationSec = value;
|
|
},
|
|
setMediaGuess: (value) => {
|
|
state.mediaGuess = value as { title: string } | null;
|
|
},
|
|
setMediaGuessPromise: (value) => {
|
|
state.mediaGuessPromise = value;
|
|
},
|
|
setLastDurationProbeAtMs: (value) => {
|
|
state.lastDurationProbeAtMs = value;
|
|
},
|
|
});
|
|
|
|
reset('/new/media');
|
|
const afterFirstReset = { ...state };
|
|
reset('/new/media');
|
|
|
|
assert.deepEqual(state, afterFirstReset);
|
|
});
|
|
|
|
test('get/set anilist media guess runtime state round-trips fields', () => {
|
|
let state = {
|
|
mediaKey: null as string | null,
|
|
mediaDurationSec: null as number | null,
|
|
mediaGuess: null as { title: string } | null,
|
|
mediaGuessPromise: null as Promise<unknown> | null,
|
|
lastDurationProbeAtMs: 0,
|
|
};
|
|
|
|
const setState = createSetAnilistMediaGuessRuntimeStateHandler({
|
|
setMediaKey: (value) => {
|
|
state.mediaKey = value;
|
|
},
|
|
setMediaDurationSec: (value) => {
|
|
state.mediaDurationSec = value;
|
|
},
|
|
setMediaGuess: (value) => {
|
|
state.mediaGuess = value as { title: string } | null;
|
|
},
|
|
setMediaGuessPromise: (value) => {
|
|
state.mediaGuessPromise = value;
|
|
},
|
|
setLastDurationProbeAtMs: (value) => {
|
|
state.lastDurationProbeAtMs = value;
|
|
},
|
|
});
|
|
|
|
const getState = createGetAnilistMediaGuessRuntimeStateHandler({
|
|
getMediaKey: () => state.mediaKey,
|
|
getMediaDurationSec: () => state.mediaDurationSec,
|
|
getMediaGuess: () => state.mediaGuess as never,
|
|
getMediaGuessPromise: () => state.mediaGuessPromise as never,
|
|
getLastDurationProbeAtMs: () => state.lastDurationProbeAtMs,
|
|
});
|
|
|
|
const nextPromise = Promise.resolve(null);
|
|
setState({
|
|
mediaKey: '/tmp/video.mkv',
|
|
mediaDurationSec: 24,
|
|
mediaGuess: { title: 'Title' } as never,
|
|
mediaGuessPromise: nextPromise as never,
|
|
lastDurationProbeAtMs: 321,
|
|
});
|
|
|
|
const roundTrip = getState();
|
|
assert.equal(roundTrip.mediaKey, '/tmp/video.mkv');
|
|
assert.equal(roundTrip.mediaDurationSec, 24);
|
|
assert.deepEqual(roundTrip.mediaGuess, { title: 'Title' });
|
|
assert.equal(roundTrip.mediaGuessPromise, nextPromise);
|
|
assert.equal(roundTrip.lastDurationProbeAtMs, 321);
|
|
});
|
|
|
|
test('reset anilist media guess state clears guess and in-flight promise', () => {
|
|
const state = {
|
|
mediaKey: '/tmp/video.mkv' as string | null,
|
|
mediaDurationSec: 240 as number | null,
|
|
mediaGuess: { title: 'guess' } as { title: string } | null,
|
|
mediaGuessPromise: Promise.resolve(null) as Promise<unknown> | null,
|
|
lastDurationProbeAtMs: 321,
|
|
};
|
|
|
|
const resetGuessState = createResetAnilistMediaGuessStateHandler({
|
|
setMediaGuess: (value) => {
|
|
state.mediaGuess = value as { title: string } | null;
|
|
},
|
|
setMediaGuessPromise: (value) => {
|
|
state.mediaGuessPromise = value;
|
|
},
|
|
});
|
|
|
|
resetGuessState();
|
|
assert.equal(state.mediaGuess, null);
|
|
assert.equal(state.mediaGuessPromise, null);
|
|
assert.equal(state.mediaKey, '/tmp/video.mkv');
|
|
assert.equal(state.mediaDurationSec, 240);
|
|
assert.equal(state.lastDurationProbeAtMs, 321);
|
|
});
|