feat(launcher): add previous episode option to history entry menu

- Extract buildHistoryEntryActions to build the series action menu, now including a previous-episode option alongside replay/next/browse/quit
- Update docs and changelog entry to describe the new option
- Add tests covering previous/replay/next ordering and omission when last watched file is missing
This commit is contained in:
2026-07-25 23:35:44 -07:00
parent e223cf9b71
commit 18c6410f24
4 changed files with 74 additions and 11 deletions
+36 -1
View File
@@ -1,7 +1,11 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import path from 'node:path';
import { buildHistorySessionActions, runHistoryPlaybackLoop } from './history-command.js';
import {
buildHistoryEntryActions,
buildHistorySessionActions,
runHistoryPlaybackLoop,
} from './history-command.js';
import type { HistorySeriesEntry } from '../history.js';
type HistoryLoop = (
@@ -186,6 +190,37 @@ test('history show menu omits previous and next when the just-played episode has
]);
});
test('history entry menu offers previous, replay, and next before playback starts', () => {
assert.equal(
typeof buildHistoryEntryActions,
'function',
'history entry actions not implemented',
);
assert.deepEqual(
buildHistoryEntryActions(
'/shows/test-show/episode-03.mkv',
'/shows/test-show/episode-02.mkv',
'/shows/test-show/episode-04.mkv',
),
[
{ kind: 'previous', label: 'Previous episode: episode-02.mkv' },
{ kind: 'replay', label: 'Replay last watched: episode-03.mkv' },
{ kind: 'next', label: 'Next episode: episode-04.mkv' },
{ kind: 'browse', label: 'Browse episodes' },
{ kind: 'quit', label: 'Quit SubMiner' },
],
);
});
test('history entry menu omits replay when the last watched file is gone', () => {
assert.deepEqual(buildHistoryEntryActions(null, null, '/shows/test-show/episode-04.mkv'), [
{ kind: 'next', label: 'Next episode: episode-04.mkv' },
{ kind: 'browse', label: 'Browse episodes' },
{ kind: 'quit', label: 'Quit SubMiner' },
]);
});
test('history playback loop selects previous based on the just-played path, then re-derives previous from the new current episode', async () => {
assert.equal(
typeof runHistoryPlaybackLoop,