mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-24 12:11:29 -07:00
feat: add app-owned YouTube subtitle flow with absPlayer-style parsing (#31)
* fix: harden preload argv parsing for popup windows * fix: align youtube playback with shared overlay startup * fix: unwrap mpv youtube streams for anki media mining * docs: update docs for youtube subtitle and mining flow * refactor: unify cli and runtime wiring for startup and youtube flow * feat: update subtitle sidebar overlay behavior * chore: add shared log-file source for diagnostics * fix(ci): add changelog fragment for immersion changes * fix: address CodeRabbit review feedback * fix: persist canonical title from youtube metadata * style: format stats library tab * fix: address latest review feedback * style: format stats library files * test: stub launcher youtube deps in CI * test: isolate launcher youtube flow deps * test: stub launcher youtube deps in failing case * test: force x11 backend in launcher ci harness * test: address latest review feedback * fix(launcher): preserve user YouTube ytdl raw options * docs(backlog): update task tracking notes * fix(immersion): special-case youtube media paths in runtime and tracking * feat(stats): improve YouTube media metadata and picker key handling * fix(ci): format stats media library hook * fix: address latest CodeRabbit review items * docs: update youtube release notes and docs * feat: auto-load youtube subtitles before manual picker * fix: restore app-owned youtube subtitle flow * docs: update youtube playback docs and config copy * refactor: remove legacy youtube launcher mode plumbing * fix: refine youtube subtitle startup binding * docs: clarify youtube subtitle startup behavior * fix: address PR #31 latest review follow-ups * fix: address PR #31 follow-up review comments * test: harden youtube picker test harness * udpate backlog * fix: add timeout to youtube metadata probe * docs: refresh youtube and stats docs * update backlog * update backlog * chore: release v0.9.0
This commit is contained in:
@@ -302,7 +302,47 @@ test('startOverlay resolves without fixed 2s sleep when readiness signals arrive
|
||||
}
|
||||
});
|
||||
|
||||
test('cleanupPlaybackSession preserves background app while stopping mpv-owned children', async () => {
|
||||
test('startOverlay captures app stdout and stderr into app log', async () => {
|
||||
const { dir, socketPath } = createTempSocketPath();
|
||||
const appPath = path.join(dir, 'fake-subminer.sh');
|
||||
const appLogPath = path.join(dir, 'app.log');
|
||||
const originalAppLog = process.env.SUBMINER_APP_LOG;
|
||||
fs.writeFileSync(
|
||||
appPath,
|
||||
'#!/bin/sh\nprintf "hello from stdout\\n"\nprintf "hello from stderr\\n" >&2\nexit 0\n',
|
||||
);
|
||||
fs.chmodSync(appPath, 0o755);
|
||||
fs.writeFileSync(socketPath, '');
|
||||
const originalCreateConnection = net.createConnection;
|
||||
try {
|
||||
process.env.SUBMINER_APP_LOG = appLogPath;
|
||||
net.createConnection = (() => {
|
||||
const socket = new EventEmitter() as net.Socket;
|
||||
socket.destroy = (() => socket) as net.Socket['destroy'];
|
||||
socket.setTimeout = (() => socket) as net.Socket['setTimeout'];
|
||||
setTimeout(() => socket.emit('connect'), 10);
|
||||
return socket;
|
||||
}) as typeof net.createConnection;
|
||||
|
||||
await startOverlay(appPath, makeArgs(), socketPath);
|
||||
|
||||
const logText = fs.readFileSync(appLogPath, 'utf8');
|
||||
assert.match(logText, /\[STDOUT\] hello from stdout/);
|
||||
assert.match(logText, /\[STDERR\] hello from stderr/);
|
||||
} finally {
|
||||
net.createConnection = originalCreateConnection;
|
||||
state.overlayProc = null;
|
||||
state.overlayManagedByLauncher = false;
|
||||
if (originalAppLog === undefined) {
|
||||
delete process.env.SUBMINER_APP_LOG;
|
||||
} else {
|
||||
process.env.SUBMINER_APP_LOG = originalAppLog;
|
||||
}
|
||||
fs.rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test('cleanupPlaybackSession stops launcher-managed overlay app and mpv-owned children', async () => {
|
||||
const { dir } = createTempSocketPath();
|
||||
const appPath = path.join(dir, 'fake-subminer.sh');
|
||||
const appInvocationsPath = path.join(dir, 'app-invocations.log');
|
||||
@@ -345,8 +385,8 @@ test('cleanupPlaybackSession preserves background app while stopping mpv-owned c
|
||||
try {
|
||||
await cleanupPlaybackSession(makeArgs());
|
||||
|
||||
assert.deepEqual(calls, ['mpv-kill', 'helper-kill']);
|
||||
assert.equal(fs.existsSync(appInvocationsPath), false);
|
||||
assert.deepEqual(calls, ['overlay-kill', 'mpv-kill', 'helper-kill']);
|
||||
assert.match(fs.readFileSync(appInvocationsPath, 'utf8'), /--stop/);
|
||||
} finally {
|
||||
state.overlayProc = null;
|
||||
state.mpvProc = null;
|
||||
|
||||
Reference in New Issue
Block a user