- Heartbeat queued jobs (before the semaphore), not just running ones, so the stale-job reaper can't fail a job that is alive but waiting for a slot (which would otherwise let it resurrect itself on acquire, or admit a duplicate once the partial unique index no longer sees it as active). - Filter the translate modal's source list to the formats the server accepts (text external/downloaded, non-bitmap embedded), so an unsupported source is prevented up front instead of failing the job asynchronously. - Tell a duplicate requester (e.g. a second viewer, or after a reload) that a translation is already in progress instead of silently closing; the finished track still arrives via the subtitle_ready refresh. - Note in the admin card that AI subtitle settings take effect after a restart (the running service snapshots them at construction). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
39 lines
1.6 KiB
TypeScript
39 lines
1.6 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { isTranslatableSource } from "./SubtitleTranslateModal";
|
|
import type { PlayerSubtitleInfo } from "../types";
|
|
|
|
function track(p: Partial<PlayerSubtitleInfo>): PlayerSubtitleInfo {
|
|
return { index: 0, language: "en", label: "", url: "", ...p };
|
|
}
|
|
|
|
describe("isTranslatableSource", () => {
|
|
it("accepts text external/downloaded subtitles", () => {
|
|
expect(isTranslatableSource(track({ source: "external", codec: "srt" }))).toBe(true);
|
|
expect(isTranslatableSource(track({ source: "downloaded", codec: "subrip" }))).toBe(true);
|
|
expect(isTranslatableSource(track({ source: "external", codec: "vtt" }))).toBe(true);
|
|
});
|
|
|
|
it("rejects ASS/SSA external/downloaded subtitles the server can't parse", () => {
|
|
expect(isTranslatableSource(track({ source: "external", codec: "ass" }))).toBe(false);
|
|
expect(isTranslatableSource(track({ source: "downloaded", codec: "ssa" }))).toBe(false);
|
|
});
|
|
|
|
it("accepts non-bitmap embedded tracks (extracted via ffmpeg, incl. ASS)", () => {
|
|
expect(isTranslatableSource(track({ source: "embedded", codec: "ass" }))).toBe(true);
|
|
expect(isTranslatableSource(track({ source: "embedded", codec: "subrip" }))).toBe(true);
|
|
});
|
|
|
|
it("rejects bitmap embedded tracks", () => {
|
|
expect(isTranslatableSource(track({ source: "embedded", codec: "hdmv_pgs_subtitle" }))).toBe(
|
|
false,
|
|
);
|
|
expect(isTranslatableSource(track({ source: "embedded", codec: "dvd_subtitle" }))).toBe(false);
|
|
});
|
|
|
|
it("rejects the in-progress live track", () => {
|
|
expect(isTranslatableSource(track({ source: "downloaded", codec: "srt", live: true }))).toBe(
|
|
false,
|
|
);
|
|
});
|
|
});
|